Jonathan Hart
Committed by Gerrit Code Review

Implementation of the NeighbourResolutionService.

Change-Id: I41fc48578df3027ec71ee7369171c8988ee7a85e
...@@ -21,36 +21,54 @@ import org.onosproject.net.host.HostService; ...@@ -21,36 +21,54 @@ import org.onosproject.net.host.HostService;
21 21
22 import java.util.Set; 22 import java.util.Set;
23 23
24 +import static org.onlab.packet.VlanId.vlanId;
24 import static org.onosproject.net.HostId.hostId; 25 import static org.onosproject.net.HostId.hostId;
25 26
26 /** 27 /**
27 - * Default neighbour message handler which implements basic proxying on a flat 28 + * Default neighbour message handler which implements basic proxying on an
28 * L2 network (i.e. ProxyArp behaviour). 29 * L2 network (i.e. ProxyArp behaviour).
29 */ 30 */
30 public class DefaultNeighbourMessageHandler implements NeighbourMessageHandler { 31 public class DefaultNeighbourMessageHandler implements NeighbourMessageHandler {
31 @Override 32 @Override
32 public void handleMessage(NeighbourMessageContext context, HostService hostService) { 33 public void handleMessage(NeighbourMessageContext context, HostService hostService) {
33 - // See if we have the target host in the host store 34 + switch (context.type()) {
34 - Set<Host> hosts = hostService.getHostsByIp(context.target()); 35 + case REPLY:
36 + Host h = hostService.getHost(hostId(context.packet().getDestinationMAC(),
37 + vlanId(context.packet().getVlanID())));
35 38
36 - Host dst = null; 39 + if (h == null) {
37 - Host src = hostService.getHost(hostId(context.srcMac(), context.vlan())); 40 + context.flood();
41 + } else {
42 + context.proxy(h.location());
43 + }
44 + break;
45 + case REQUEST:
46 + // See if we have the target host in the host store
47 + Set<Host> hosts = hostService.getHostsByIp(context.target());
48 +
49 + Host dst = null;
50 + Host src = hostService.getHost(hostId(context.srcMac(), context.vlan()));
38 51
39 - for (Host host : hosts) { 52 + for (Host host : hosts) {
40 - if (host.vlan().equals(context.vlan())) { 53 + if (host.vlan().equals(context.vlan())) {
41 - dst = host; 54 + dst = host;
42 - break; 55 + break;
56 + }
57 + }
58 +
59 + if (src != null && dst != null) {
60 + // We know the target host so we can respond
61 + context.reply(dst.mac());
62 + return;
43 } 63 }
44 - }
45 64
46 - if (src != null && dst != null) { 65 + // The request couldn't be resolved.
47 - // We know the target host so we can respond 66 + // Flood the request on all ports except the incoming port.
48 - context.reply(dst.mac()); 67 + context.flood();
49 - return; 68 + break;
69 + default:
70 + break;
50 } 71 }
51 72
52 - // The request couldn't be resolved.
53 - // Flood the request on all ports except the incoming port.
54 - context.flood();
55 } 73 }
56 } 74 }
......
...@@ -24,8 +24,6 @@ import org.onlab.packet.VlanId; ...@@ -24,8 +24,6 @@ import org.onlab.packet.VlanId;
24 import org.onosproject.incubator.net.intf.Interface; 24 import org.onosproject.incubator.net.intf.Interface;
25 import org.onosproject.net.ConnectPoint; 25 import org.onosproject.net.ConnectPoint;
26 26
27 -import static com.google.common.base.Preconditions.checkState;
28 -
29 /** 27 /**
30 * Context of an incoming neighbor message (e.g. ARP, NDP). 28 * Context of an incoming neighbor message (e.g. ARP, NDP).
31 * 29 *
...@@ -34,156 +32,91 @@ import static com.google.common.base.Preconditions.checkState; ...@@ -34,156 +32,91 @@ import static com.google.common.base.Preconditions.checkState;
34 * response to the incoming message.</p> 32 * response to the incoming message.</p>
35 */ 33 */
36 @Beta 34 @Beta
37 -public class NeighbourMessageContext { 35 +public interface NeighbourMessageContext {
38 -
39 - private final NeighbourProtocol protocol;
40 - private final NeighbourMessageType type;
41 -
42 - private final IpAddress target;
43 - private final IpAddress sender;
44 -
45 - private final Ethernet eth;
46 - private final ConnectPoint inPort;
47 -
48 - private final NeighbourMessageActions actions;
49 -
50 - /**
51 - * Creates a new neighbour message context.
52 - *
53 - * @param actions actions
54 - * @param eth ethernet frame
55 - * @param inPort incoming port
56 - * @param protocol message protocol
57 - * @param type message type
58 - * @param target target IP address
59 - * @param sender sender IP address
60 - */
61 - public NeighbourMessageContext(NeighbourMessageActions actions,
62 - Ethernet eth, ConnectPoint inPort,
63 - NeighbourProtocol protocol, NeighbourMessageType type,
64 - IpAddress target, IpAddress sender) {
65 - this.actions = actions;
66 - this.eth = eth;
67 - this.inPort = inPort;
68 - this.protocol = protocol;
69 - this.type = type;
70 - this.target = target;
71 - this.sender = sender;
72 - }
73 -
74 /** 36 /**
75 * Gets the port where the packet came in to the network. 37 * Gets the port where the packet came in to the network.
76 * 38 *
77 * @return connect point 39 * @return connect point
78 */ 40 */
79 - public ConnectPoint inPort() { 41 + ConnectPoint inPort();
80 - return inPort;
81 - }
82 42
83 /** 43 /**
84 * Gets the full parsed representation of the packet. 44 * Gets the full parsed representation of the packet.
85 * 45 *
86 * @return ethernet header 46 * @return ethernet header
87 */ 47 */
88 - public Ethernet packet() { 48 + Ethernet packet();
89 - return eth;
90 - }
91 49
92 /** 50 /**
93 * Gets the protocol of the packet. 51 * Gets the protocol of the packet.
94 * 52 *
95 * @return protocol 53 * @return protocol
96 */ 54 */
97 - public NeighbourProtocol protocol() { 55 + NeighbourProtocol protocol();
98 - return protocol;
99 - }
100 56
101 /** 57 /**
102 * Gets the message type of the packet. 58 * Gets the message type of the packet.
103 * 59 *
104 * @return message type 60 * @return message type
105 */ 61 */
106 - public NeighbourMessageType type() { 62 + NeighbourMessageType type();
107 - return type;
108 - }
109 63
110 /** 64 /**
111 * Gets the vlan of the packet, if any. 65 * Gets the vlan of the packet, if any.
112 * 66 *
113 * @return vlan 67 * @return vlan
114 */ 68 */
115 - public VlanId vlan() { 69 + VlanId vlan();
116 - return VlanId.vlanId(eth.getVlanID());
117 - }
118 70
119 /** 71 /**
120 * Gets the source MAC address of the message. 72 * Gets the source MAC address of the message.
121 * 73 *
122 * @return source MAC address 74 * @return source MAC address
123 */ 75 */
124 - public MacAddress srcMac() { 76 + MacAddress srcMac();
125 - return MacAddress.valueOf(eth.getSourceMACAddress());
126 - }
127 77
128 /** 78 /**
129 * Gets the target IP address of the message. 79 * Gets the target IP address of the message.
130 * 80 *
131 * @return target IP address 81 * @return target IP address
132 */ 82 */
133 - public IpAddress target() { 83 + IpAddress target();
134 - return target;
135 - }
136 84
137 /** 85 /**
138 * Gets the source IP address of the message. 86 * Gets the source IP address of the message.
139 * 87 *
140 * @return source IP address 88 * @return source IP address
141 */ 89 */
142 - public IpAddress sender() { 90 + IpAddress sender();
143 - return sender;
144 - }
145 91
146 /** 92 /**
147 * Proxies the message to a given output port. 93 * Proxies the message to a given output port.
148 * 94 *
149 * @param outPort output port 95 * @param outPort output port
150 */ 96 */
151 - public void proxy(ConnectPoint outPort) { 97 + void proxy(ConnectPoint outPort);
152 - actions.proxy(this, outPort);
153 - }
154 98
155 /** 99 /**
156 * Proxies the message to a given interface. 100 * Proxies the message to a given interface.
157 * 101 *
158 * @param outIntf output interface 102 * @param outIntf output interface
159 */ 103 */
160 - public void proxy(Interface outIntf) { 104 + void proxy(Interface outIntf);
161 - actions.proxy(this, outIntf);
162 - }
163 105
164 /** 106 /**
165 * Replies to the request message with a given MAC address. 107 * Replies to the request message with a given MAC address.
166 * 108 *
167 * @param targetMac target MAC address 109 * @param targetMac target MAC address
168 */ 110 */
169 - public void reply(MacAddress targetMac) { 111 + void reply(MacAddress targetMac);
170 - checkState(type == NeighbourMessageType.REQUEST, "can only reply to requests");
171 -
172 - actions.reply(this, targetMac);
173 - }
174 112
175 /** 113 /**
176 * Floods the incoming message out all ports except the input port. 114 * Floods the incoming message out all ports except the input port.
177 */ 115 */
178 - public void flood() { 116 + void flood();
179 - actions.flood(this);
180 - }
181 117
182 /** 118 /**
183 * Drops the incoming message. 119 * Drops the incoming message.
184 */ 120 */
185 - public void drop() { 121 + void drop();
186 - actions.drop(this);
187 - }
188 -
189 } 122 }
......
...@@ -45,4 +45,20 @@ public interface NeighbourResolutionService { ...@@ -45,4 +45,20 @@ public interface NeighbourResolutionService {
45 */ 45 */
46 void registerNeighbourHandler(Interface intf, NeighbourMessageHandler handler); 46 void registerNeighbourHandler(Interface intf, NeighbourMessageHandler handler);
47 47
48 + /**
49 + * Unregisters a neighbour message handler that was assigned to a connect
50 + * point.
51 + *
52 + * @param connectPoint connect point
53 + * @param handler neighbour message handler
54 + */
55 + void unregisterNeighbourHandler(ConnectPoint connectPoint, NeighbourMessageHandler handler);
56 +
57 + /**
58 + * Unregisters a neighbour message handler that was assigned to an interface.
59 + *
60 + * @param intf interface
61 + * @param handler neighbour message handler
62 + */
63 + void unregisterNeighbourHandler(Interface intf, NeighbourMessageHandler handler);
48 } 64 }
......
1 +/*
2 + * Copyright 2016-present Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.incubator.net.neighbour.impl;
18 +
19 +import com.google.common.annotations.Beta;
20 +import org.onlab.packet.ARP;
21 +import org.onlab.packet.Ethernet;
22 +import org.onlab.packet.ICMP6;
23 +import org.onlab.packet.IPv6;
24 +import org.onlab.packet.Ip4Address;
25 +import org.onlab.packet.Ip6Address;
26 +import org.onlab.packet.IpAddress;
27 +import org.onlab.packet.MacAddress;
28 +import org.onlab.packet.VlanId;
29 +import org.onlab.packet.ndp.NeighborSolicitation;
30 +import org.onosproject.incubator.net.intf.Interface;
31 +import org.onosproject.incubator.net.neighbour.NeighbourMessageActions;
32 +import org.onosproject.incubator.net.neighbour.NeighbourMessageContext;
33 +import org.onosproject.incubator.net.neighbour.NeighbourMessageType;
34 +import org.onosproject.incubator.net.neighbour.NeighbourProtocol;
35 +import org.onosproject.net.ConnectPoint;
36 +
37 +import static com.google.common.base.Preconditions.checkState;
38 +
39 +/**
40 + * Default implementation of a neighbour message context.
41 + */
42 +@Beta
43 +public class DefaultNeighbourMessageContext implements NeighbourMessageContext {
44 +
45 + private final NeighbourProtocol protocol;
46 + private final NeighbourMessageType type;
47 +
48 + private final IpAddress target;
49 + private final IpAddress sender;
50 +
51 + private final Ethernet eth;
52 + private final ConnectPoint inPort;
53 +
54 + private final NeighbourMessageActions actions;
55 +
56 + /**
57 + * Creates a new neighbour message context.
58 + *
59 + * @param actions actions
60 + * @param eth ethernet frame
61 + * @param inPort incoming port
62 + * @param protocol message protocol
63 + * @param type message type
64 + * @param target target IP address
65 + * @param sender sender IP address
66 + */
67 + DefaultNeighbourMessageContext(NeighbourMessageActions actions,
68 + Ethernet eth, ConnectPoint inPort,
69 + NeighbourProtocol protocol,
70 + NeighbourMessageType type,
71 + IpAddress target, IpAddress sender) {
72 + this.actions = actions;
73 + this.eth = eth;
74 + this.inPort = inPort;
75 + this.protocol = protocol;
76 + this.type = type;
77 + this.target = target;
78 + this.sender = sender;
79 + }
80 +
81 + @Override
82 + public ConnectPoint inPort() {
83 + return inPort;
84 + }
85 +
86 + @Override
87 + public Ethernet packet() {
88 + return eth;
89 + }
90 +
91 + @Override
92 + public NeighbourProtocol protocol() {
93 + return protocol;
94 + }
95 +
96 + @Override
97 + public NeighbourMessageType type() {
98 + return type;
99 + }
100 +
101 + @Override
102 + public VlanId vlan() {
103 + return VlanId.vlanId(eth.getVlanID());
104 + }
105 +
106 + @Override
107 + public MacAddress srcMac() {
108 + return MacAddress.valueOf(eth.getSourceMACAddress());
109 + }
110 +
111 + @Override
112 + public IpAddress target() {
113 + return target;
114 + }
115 +
116 + @Override
117 + public IpAddress sender() {
118 + return sender;
119 + }
120 +
121 + @Override
122 + public void proxy(ConnectPoint outPort) {
123 + actions.proxy(this, outPort);
124 + }
125 +
126 + @Override
127 + public void proxy(Interface outIntf) {
128 + actions.proxy(this, outIntf);
129 + }
130 +
131 + @Override
132 + public void reply(MacAddress targetMac) {
133 + checkState(type == NeighbourMessageType.REQUEST, "can only reply to requests");
134 +
135 + actions.reply(this, targetMac);
136 + }
137 +
138 + @Override
139 + public void flood() {
140 + actions.flood(this);
141 + }
142 +
143 + @Override
144 + public void drop() {
145 + actions.drop(this);
146 + }
147 +
148 + /**
149 + * Attempts to create a MessageContext for the given Ethernet frame. If the
150 + * frame is a valid ARP or NDP request or response, a context will be
151 + * created.
152 + *
153 + * @param eth input Ethernet frame
154 + * @param inPort in port
155 + * @return MessageContext if the packet was ARP or NDP, otherwise null
156 + */
157 + public static NeighbourMessageContext createContext(Ethernet eth,
158 + ConnectPoint inPort,
159 + NeighbourMessageActions actions) {
160 + if (eth.getEtherType() == Ethernet.TYPE_ARP) {
161 + return createArpContext(eth, inPort, actions);
162 + } else if (eth.getEtherType() == Ethernet.TYPE_IPV6) {
163 + return createNdpContext(eth, inPort, actions);
164 + }
165 +
166 + return null;
167 + }
168 +
169 + /**
170 + * Extracts context information from ARP packets.
171 + *
172 + * @param eth input Ethernet frame that is thought to be ARP
173 + * @param inPort in port
174 + * @return MessageContext object if the packet was a valid ARP packet,
175 + * otherwise null
176 + */
177 + private static NeighbourMessageContext createArpContext(Ethernet eth,
178 + ConnectPoint inPort,
179 + NeighbourMessageActions actions) {
180 + if (eth.getEtherType() != Ethernet.TYPE_ARP) {
181 + return null;
182 + }
183 +
184 + ARP arp = (ARP) eth.getPayload();
185 +
186 + IpAddress target = Ip4Address.valueOf(arp.getTargetProtocolAddress());
187 + IpAddress sender = Ip4Address.valueOf(arp.getSenderProtocolAddress());
188 +
189 + NeighbourMessageType type;
190 + if (arp.getOpCode() == ARP.OP_REQUEST) {
191 + type = NeighbourMessageType.REQUEST;
192 + } else if (arp.getOpCode() == ARP.OP_REPLY) {
193 + type = NeighbourMessageType.REPLY;
194 + } else {
195 + return null;
196 + }
197 +
198 + return new DefaultNeighbourMessageContext(actions, eth, inPort,
199 + NeighbourProtocol.ARP, type, target, sender);
200 + }
201 +
202 + /**
203 + * Extracts context information from NDP packets.
204 + *
205 + * @param eth input Ethernet frame that is thought to be NDP
206 + * @param inPort in port
207 + * @return MessageContext object if the packet was a valid NDP packet,
208 + * otherwise null
209 + */
210 + private static NeighbourMessageContext createNdpContext(Ethernet eth,
211 + ConnectPoint inPort,
212 + NeighbourMessageActions actions) {
213 + if (eth.getEtherType() != Ethernet.TYPE_IPV6) {
214 + return null;
215 + }
216 + IPv6 ipv6 = (IPv6) eth.getPayload();
217 +
218 + if (ipv6.getNextHeader() != IPv6.PROTOCOL_ICMP6) {
219 + return null;
220 + }
221 + ICMP6 icmpv6 = (ICMP6) ipv6.getPayload();
222 +
223 + IpAddress sender = Ip6Address.valueOf(ipv6.getSourceAddress());
224 + IpAddress target = null;
225 +
226 + NeighbourMessageType type;
227 + if (icmpv6.getIcmpType() == ICMP6.NEIGHBOR_SOLICITATION) {
228 + type = NeighbourMessageType.REQUEST;
229 + NeighborSolicitation nsol = (NeighborSolicitation) icmpv6.getPayload();
230 + target = Ip6Address.valueOf(nsol.getTargetAddress());
231 + } else if (icmpv6.getIcmpType() == ICMP6.NEIGHBOR_ADVERTISEMENT) {
232 + type = NeighbourMessageType.REPLY;
233 + } else {
234 + return null;
235 + }
236 +
237 + return new DefaultNeighbourMessageContext(actions, eth, inPort,
238 + NeighbourProtocol.NDP, type, target, sender);
239 + }
240 +
241 +}
1 +/*
2 + * Copyright 2016-present Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +/**
18 + * Implementation of neighbour resolution service.
19 + */
20 +package org.onosproject.incubator.net.neighbour.impl;