initial impl of proxy arp
Change-Id: I131667e8051e88c27f5fa020b580be57fee358ea
Showing
6 changed files
with
183 additions
and
21 deletions
1 | +package org.onlab.onos.net.proxyarp; | ||
2 | + | ||
3 | +import org.onlab.packet.Ethernet; | ||
4 | +import org.onlab.packet.IpPrefix; | ||
5 | + | ||
6 | +/** | ||
7 | + * Service for processing arp requests on behalf of applications. | ||
8 | + */ | ||
9 | +public interface ProxyArpService { | ||
10 | + | ||
11 | + /** | ||
12 | + * Returns whether this particular ip address is known to the system. | ||
13 | + * | ||
14 | + * @param addr | ||
15 | + * a ip address | ||
16 | + * @return true if know, false otherwise | ||
17 | + */ | ||
18 | + boolean known(IpPrefix addr); | ||
19 | + | ||
20 | + /** | ||
21 | + * Sends a reply for a given request. If the host is not known then the arp | ||
22 | + * will be flooded at all edge ports. | ||
23 | + * | ||
24 | + * @param request | ||
25 | + * an arp request | ||
26 | + */ | ||
27 | + void reply(Ethernet request); | ||
28 | + | ||
29 | +} |
... | @@ -45,9 +45,9 @@ import org.slf4j.Logger; | ... | @@ -45,9 +45,9 @@ import org.slf4j.Logger; |
45 | */ | 45 | */ |
46 | @Component(immediate = true) | 46 | @Component(immediate = true) |
47 | @Service | 47 | @Service |
48 | -public class DeviceManager | 48 | +public class DeviceManager extends |
49 | -extends AbstractProviderRegistry<DeviceProvider, DeviceProviderService> | 49 | + AbstractProviderRegistry<DeviceProvider, DeviceProviderService> implements |
50 | -implements DeviceService, DeviceAdminService, DeviceProviderRegistry { | 50 | + DeviceService, DeviceAdminService, DeviceProviderRegistry { |
51 | 51 | ||
52 | private static final String DEVICE_ID_NULL = "Device ID cannot be null"; | 52 | private static final String DEVICE_ID_NULL = "Device ID cannot be null"; |
53 | private static final String PORT_NUMBER_NULL = "Port number cannot be null"; | 53 | private static final String PORT_NUMBER_NULL = "Port number cannot be null"; |
... | @@ -57,8 +57,7 @@ implements DeviceService, DeviceAdminService, DeviceProviderRegistry { | ... | @@ -57,8 +57,7 @@ implements DeviceService, DeviceAdminService, DeviceProviderRegistry { |
57 | 57 | ||
58 | private final Logger log = getLogger(getClass()); | 58 | private final Logger log = getLogger(getClass()); |
59 | 59 | ||
60 | - protected final AbstractListenerRegistry<DeviceEvent, DeviceListener> | 60 | + protected final AbstractListenerRegistry<DeviceEvent, DeviceListener> listenerRegistry = new AbstractListenerRegistry<>(); |
61 | - listenerRegistry = new AbstractListenerRegistry<>(); | ||
62 | 61 | ||
63 | private final DeviceStoreDelegate delegate = new InternalStoreDelegate(); | 62 | private final DeviceStoreDelegate delegate = new InternalStoreDelegate(); |
64 | 63 | ||
... | @@ -169,28 +168,31 @@ implements DeviceService, DeviceAdminService, DeviceProviderRegistry { | ... | @@ -169,28 +168,31 @@ implements DeviceService, DeviceAdminService, DeviceProviderRegistry { |
169 | } | 168 | } |
170 | 169 | ||
171 | @Override | 170 | @Override |
172 | - protected DeviceProviderService createProviderService(DeviceProvider provider) { | 171 | + protected DeviceProviderService createProviderService( |
172 | + DeviceProvider provider) { | ||
173 | return new InternalDeviceProviderService(provider); | 173 | return new InternalDeviceProviderService(provider); |
174 | } | 174 | } |
175 | 175 | ||
176 | // Personalized device provider service issued to the supplied provider. | 176 | // Personalized device provider service issued to the supplied provider. |
177 | - private class InternalDeviceProviderService | 177 | + private class InternalDeviceProviderService extends |
178 | - extends AbstractProviderService<DeviceProvider> | 178 | + AbstractProviderService<DeviceProvider> implements |
179 | - implements DeviceProviderService { | 179 | + DeviceProviderService { |
180 | 180 | ||
181 | InternalDeviceProviderService(DeviceProvider provider) { | 181 | InternalDeviceProviderService(DeviceProvider provider) { |
182 | super(provider); | 182 | super(provider); |
183 | } | 183 | } |
184 | 184 | ||
185 | @Override | 185 | @Override |
186 | - public void deviceConnected(DeviceId deviceId, DeviceDescription deviceDescription) { | 186 | + public void deviceConnected(DeviceId deviceId, |
187 | + DeviceDescription deviceDescription) { | ||
187 | checkNotNull(deviceId, DEVICE_ID_NULL); | 188 | checkNotNull(deviceId, DEVICE_ID_NULL); |
188 | checkNotNull(deviceDescription, DEVICE_DESCRIPTION_NULL); | 189 | checkNotNull(deviceDescription, DEVICE_DESCRIPTION_NULL); |
189 | checkValidity(); | 190 | checkValidity(); |
190 | DeviceEvent event = store.createOrUpdateDevice(provider().id(), | 191 | DeviceEvent event = store.createOrUpdateDevice(provider().id(), |
191 | deviceId, deviceDescription); | 192 | deviceId, deviceDescription); |
192 | 193 | ||
193 | - // If there was a change of any kind, trigger role selection process. | 194 | + // If there was a change of any kind, trigger role selection |
195 | + // process. | ||
194 | if (event != null) { | 196 | if (event != null) { |
195 | log.info("Device {} connected", deviceId); | 197 | log.info("Device {} connected", deviceId); |
196 | mastershipService.requestRoleFor(deviceId); | 198 | mastershipService.requestRoleFor(deviceId); |
... | @@ -212,25 +214,30 @@ implements DeviceService, DeviceAdminService, DeviceProviderRegistry { | ... | @@ -212,25 +214,30 @@ implements DeviceService, DeviceAdminService, DeviceProviderRegistry { |
212 | } | 214 | } |
213 | 215 | ||
214 | @Override | 216 | @Override |
215 | - public void updatePorts(DeviceId deviceId, List<PortDescription> portDescriptions) { | 217 | + public void updatePorts(DeviceId deviceId, |
218 | + List<PortDescription> portDescriptions) { | ||
216 | checkNotNull(deviceId, DEVICE_ID_NULL); | 219 | checkNotNull(deviceId, DEVICE_ID_NULL); |
217 | - checkNotNull(portDescriptions, "Port descriptions list cannot be null"); | 220 | + checkNotNull(portDescriptions, |
221 | + "Port descriptions list cannot be null"); | ||
218 | checkValidity(); | 222 | checkValidity(); |
219 | - List<DeviceEvent> events = store.updatePorts(deviceId, portDescriptions); | 223 | + List<DeviceEvent> events = store.updatePorts(deviceId, |
224 | + portDescriptions); | ||
220 | for (DeviceEvent event : events) { | 225 | for (DeviceEvent event : events) { |
221 | post(event); | 226 | post(event); |
222 | } | 227 | } |
223 | } | 228 | } |
224 | 229 | ||
225 | @Override | 230 | @Override |
226 | - public void portStatusChanged(DeviceId deviceId, PortDescription portDescription) { | 231 | + public void portStatusChanged(DeviceId deviceId, |
232 | + PortDescription portDescription) { | ||
227 | checkNotNull(deviceId, DEVICE_ID_NULL); | 233 | checkNotNull(deviceId, DEVICE_ID_NULL); |
228 | checkNotNull(portDescription, PORT_DESCRIPTION_NULL); | 234 | checkNotNull(portDescription, PORT_DESCRIPTION_NULL); |
229 | checkValidity(); | 235 | checkValidity(); |
230 | - DeviceEvent event = store.updatePortStatus(deviceId, portDescription); | 236 | + DeviceEvent event = store.updatePortStatus(deviceId, |
237 | + portDescription); | ||
231 | if (event != null) { | 238 | if (event != null) { |
232 | - log.info("Device {} port {} status changed", deviceId, | 239 | + log.info("Device {} port {} status changed", deviceId, event |
233 | - event.port().number()); | 240 | + .port().number()); |
234 | post(event); | 241 | post(event); |
235 | } | 242 | } |
236 | } | 243 | } |
... | @@ -238,8 +245,8 @@ implements DeviceService, DeviceAdminService, DeviceProviderRegistry { | ... | @@ -238,8 +245,8 @@ implements DeviceService, DeviceAdminService, DeviceProviderRegistry { |
238 | @Override | 245 | @Override |
239 | public void unableToAssertRole(DeviceId deviceId, MastershipRole role) { | 246 | public void unableToAssertRole(DeviceId deviceId, MastershipRole role) { |
240 | // FIXME: implement response to this notification | 247 | // FIXME: implement response to this notification |
241 | - log.warn("Failed to assert role [{}] onto Device {}", | 248 | + log.warn("Failed to assert role [{}] onto Device {}", role, |
242 | - role, deviceId); | 249 | + deviceId); |
243 | } | 250 | } |
244 | } | 251 | } |
245 | 252 | ||
... | @@ -255,7 +262,8 @@ implements DeviceService, DeviceAdminService, DeviceProviderRegistry { | ... | @@ -255,7 +262,8 @@ implements DeviceService, DeviceAdminService, DeviceProviderRegistry { |
255 | @Override | 262 | @Override |
256 | public void event(MastershipEvent event) { | 263 | public void event(MastershipEvent event) { |
257 | if (event.master().equals(clusterService.getLocalNode().id())) { | 264 | if (event.master().equals(clusterService.getLocalNode().id())) { |
258 | - MastershipTerm term = mastershipService.requestTermService().getMastershipTerm(event.subject()); | 265 | + MastershipTerm term = mastershipService.requestTermService() |
266 | + .getMastershipTerm(event.subject()); | ||
259 | clockService.setMastershipTerm(event.subject(), term); | 267 | clockService.setMastershipTerm(event.subject(), term); |
260 | applyRole(event.subject(), MastershipRole.MASTER); | 268 | applyRole(event.subject(), MastershipRole.MASTER); |
261 | } else { | 269 | } else { | ... | ... |
1 | +package org.onlab.onos.proxyarp.impl; | ||
2 | + | ||
3 | +import static com.google.common.base.Preconditions.checkArgument; | ||
4 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
5 | + | ||
6 | +import java.nio.ByteBuffer; | ||
7 | +import java.util.Set; | ||
8 | + | ||
9 | +import org.apache.felix.scr.annotations.Reference; | ||
10 | +import org.apache.felix.scr.annotations.ReferenceCardinality; | ||
11 | +import org.onlab.onos.net.Host; | ||
12 | +import org.onlab.onos.net.flow.DefaultTrafficTreatment; | ||
13 | +import org.onlab.onos.net.flow.TrafficTreatment; | ||
14 | +import org.onlab.onos.net.host.HostService; | ||
15 | +import org.onlab.onos.net.packet.DefaultOutboundPacket; | ||
16 | +import org.onlab.onos.net.packet.PacketService; | ||
17 | +import org.onlab.onos.net.proxyarp.ProxyArpService; | ||
18 | +import org.onlab.onos.net.topology.TopologyService; | ||
19 | +import org.onlab.packet.ARP; | ||
20 | +import org.onlab.packet.Ethernet; | ||
21 | +import org.onlab.packet.IpPrefix; | ||
22 | +import org.onlab.packet.VlanId; | ||
23 | + | ||
24 | +public class ProxyArpManager implements ProxyArpService { | ||
25 | + | ||
26 | + private static final String MAC_ADDR_NULL = "Mac address cannot be null."; | ||
27 | + private static final String REQUEST_NULL = "Arp request cannot be null."; | ||
28 | + private static final String REQUEST_NOT_ARP = "Ethernet frame does not contain ARP request."; | ||
29 | + private static final String NOT_ARP_REQUEST = "ARP is not a request."; | ||
30 | + | ||
31 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
32 | + protected HostService hostService; | ||
33 | + | ||
34 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
35 | + protected PacketService packetService; | ||
36 | + | ||
37 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
38 | + protected TopologyService topologyService; | ||
39 | + | ||
40 | + @Override | ||
41 | + public boolean known(IpPrefix addr) { | ||
42 | + checkNotNull(MAC_ADDR_NULL, addr); | ||
43 | + Set<Host> hosts = hostService.getHostsByIp(addr); | ||
44 | + return !hosts.isEmpty(); | ||
45 | + } | ||
46 | + | ||
47 | + @Override | ||
48 | + public void reply(Ethernet request) { | ||
49 | + checkNotNull(REQUEST_NULL, request); | ||
50 | + checkArgument(request.getEtherType() == Ethernet.TYPE_ARP, | ||
51 | + REQUEST_NOT_ARP); | ||
52 | + ARP arp = (ARP) request.getPayload(); | ||
53 | + checkArgument(arp.getOpCode() == ARP.OP_REQUEST, NOT_ARP_REQUEST); | ||
54 | + | ||
55 | + VlanId vlan = VlanId.vlanId(request.getVlanID()); | ||
56 | + Set<Host> hosts = hostService.getHostsByIp(IpPrefix.valueOf(arp | ||
57 | + .getTargetProtocolAddress())); | ||
58 | + | ||
59 | + Host h = null; | ||
60 | + for (Host host : hosts) { | ||
61 | + if (host.vlan().equals(vlan)) { | ||
62 | + h = host; | ||
63 | + break; | ||
64 | + } | ||
65 | + } | ||
66 | + | ||
67 | + if (h == null) { | ||
68 | + flood(request); | ||
69 | + return; | ||
70 | + } | ||
71 | + | ||
72 | + Ethernet arpReply = buildArpReply(h, request); | ||
73 | + // TODO: check send status with host service. | ||
74 | + TrafficTreatment.Builder builder = new DefaultTrafficTreatment.Builder(); | ||
75 | + builder.setOutput(h.location().port()); | ||
76 | + packetService.emit(new DefaultOutboundPacket(h.location().deviceId(), | ||
77 | + builder.build(), ByteBuffer.wrap(arpReply.serialize()))); | ||
78 | + } | ||
79 | + | ||
80 | + private void flood(Ethernet request) { | ||
81 | + // TODO: flood on all edge ports. | ||
82 | + } | ||
83 | + | ||
84 | + private Ethernet buildArpReply(Host h, Ethernet request) { | ||
85 | + Ethernet eth = new Ethernet(); | ||
86 | + eth.setDestinationMACAddress(request.getSourceMACAddress()); | ||
87 | + eth.setSourceMACAddress(h.mac().getAddress()); | ||
88 | + eth.setEtherType(Ethernet.TYPE_ARP); | ||
89 | + ARP arp = new ARP(); | ||
90 | + arp.setOpCode(ARP.OP_REPLY); | ||
91 | + arp.setSenderHardwareAddress(h.mac().getAddress()); | ||
92 | + arp.setTargetHardwareAddress(request.getSourceMACAddress()); | ||
93 | + | ||
94 | + arp.setTargetProtocolAddress(((ARP) request.getPayload()) | ||
95 | + .getSenderProtocolAddress()); | ||
96 | + arp.setSenderProtocolAddress(h.ipAddresses().iterator().next().toInt()); | ||
97 | + eth.setPayload(arp); | ||
98 | + return eth; | ||
99 | + } | ||
100 | +} |
tools/test/bin/onos-start-network
0 → 100755
1 | +#!/bin/bash | ||
2 | +#------------------------------------------------------------------------------- | ||
3 | +# Verifies connectivity to each node in ONOS cell. | ||
4 | +#------------------------------------------------------------------------------- | ||
5 | + | ||
6 | +[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1 | ||
7 | +. $ONOS_ROOT/tools/build/envDefaults | ||
8 | + | ||
9 | +SSHCMD="ssh -o PasswordAuthentication=no" | ||
10 | +SCPCMD="scp -q -o PasswordAuthentication=no" | ||
11 | + | ||
12 | +echo "Copying topology files to mininet vm." | ||
13 | +$SSHCMD -n $ONOS_USER@$OCN mkdir -p topos | ||
14 | +$SCPCMD $ONOS_ROOT/tools/test/topos/* $ONOS_USER@$OCN:topos/ | ||
15 | + | ||
16 | +echo "Starting Network." | ||
17 | +$SSHCMD -t $ONOS_USER@$OCN sudo python topos/sol.py $(env | sort | egrep "OC[0-9]+" | cut -d= -f2) |
-
Please register or login to post a comment