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