Pavlin Radoslavov

Add explicit flow rules to receive control packets: ARP, LLDP, BDDP

This fixes ONOS-540

NOTES:
 * Currently, the flow rules are pushed by each module that needs to receive
   the corresponding control packets:
   - ARP: ProxyArpManager, HostLocationProvider
   - LLDP and BDDP: LLDPLinkProvider
 * Pushing the corresponding IPv6 rules for Neighbor Discovery is not done yet
 * In the future, we might want to consider an explicit service to
   subscribe for receiving particular control packets

[Merge from master with manual conflict resolution]

Change-Id: I292ad11a2e48390624f381c278e55e5d0af93c6d
...@@ -31,6 +31,8 @@ import org.apache.felix.scr.annotations.Deactivate; ...@@ -31,6 +31,8 @@ import org.apache.felix.scr.annotations.Deactivate;
31 import org.apache.felix.scr.annotations.Reference; 31 import org.apache.felix.scr.annotations.Reference;
32 import org.apache.felix.scr.annotations.ReferenceCardinality; 32 import org.apache.felix.scr.annotations.ReferenceCardinality;
33 import org.apache.felix.scr.annotations.Service; 33 import org.apache.felix.scr.annotations.Service;
34 +import org.onosproject.core.ApplicationId;
35 +import org.onosproject.core.CoreService;
34 import org.onosproject.net.ConnectPoint; 36 import org.onosproject.net.ConnectPoint;
35 import org.onosproject.net.Device; 37 import org.onosproject.net.Device;
36 import org.onosproject.net.Host; 38 import org.onosproject.net.Host;
...@@ -41,7 +43,12 @@ import org.onosproject.net.PortNumber; ...@@ -41,7 +43,12 @@ import org.onosproject.net.PortNumber;
41 import org.onosproject.net.device.DeviceEvent; 43 import org.onosproject.net.device.DeviceEvent;
42 import org.onosproject.net.device.DeviceListener; 44 import org.onosproject.net.device.DeviceListener;
43 import org.onosproject.net.device.DeviceService; 45 import org.onosproject.net.device.DeviceService;
46 +import org.onosproject.net.flow.DefaultFlowRule;
47 +import org.onosproject.net.flow.DefaultTrafficSelector;
44 import org.onosproject.net.flow.DefaultTrafficTreatment; 48 import org.onosproject.net.flow.DefaultTrafficTreatment;
49 +import org.onosproject.net.flow.FlowRule;
50 +import org.onosproject.net.flow.FlowRuleService;
51 +import org.onosproject.net.flow.TrafficSelector;
45 import org.onosproject.net.flow.TrafficTreatment; 52 import org.onosproject.net.flow.TrafficTreatment;
46 import org.onosproject.net.host.HostService; 53 import org.onosproject.net.host.HostService;
47 import org.onosproject.net.host.InterfaceIpAddress; 54 import org.onosproject.net.host.InterfaceIpAddress;
...@@ -72,6 +79,8 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -72,6 +79,8 @@ public class ProxyArpManager implements ProxyArpService {
72 79
73 private final Logger log = getLogger(getClass()); 80 private final Logger log = getLogger(getClass());
74 81
82 + private static final int FLOW_RULE_PRIORITY = 40000;
83 +
75 private static final String MAC_ADDR_NULL = "Mac address cannot be null."; 84 private static final String MAC_ADDR_NULL = "Mac address cannot be null.";
76 private static final String REQUEST_NULL = "Arp request cannot be null."; 85 private static final String REQUEST_NULL = "Arp request cannot be null.";
77 private static final String REQUEST_NOT_ARP = "Ethernet frame does not contain ARP request."; 86 private static final String REQUEST_NOT_ARP = "Ethernet frame does not contain ARP request.";
...@@ -79,6 +88,12 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -79,6 +88,12 @@ public class ProxyArpManager implements ProxyArpService {
79 private static final String NOT_ARP_REPLY = "ARP is not a reply."; 88 private static final String NOT_ARP_REPLY = "ARP is not a reply.";
80 89
81 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 90 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
91 + protected CoreService coreService;
92 +
93 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
94 + protected FlowRuleService flowRuleService;
95 +
96 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
82 protected HostService hostService; 97 protected HostService hostService;
83 98
84 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 99 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
...@@ -96,15 +111,22 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -96,15 +111,22 @@ public class ProxyArpManager implements ProxyArpService {
96 private final Multimap<Device, PortNumber> externalPorts = 111 private final Multimap<Device, PortNumber> externalPorts =
97 HashMultimap.<Device, PortNumber>create(); 112 HashMultimap.<Device, PortNumber>create();
98 113
114 + private ApplicationId appId;
115 +
99 /** 116 /**
100 * Listens to both device service and link service to determine 117 * Listens to both device service and link service to determine
101 * whether a port is internal or external. 118 * whether a port is internal or external.
102 */ 119 */
103 @Activate 120 @Activate
104 public void activate() { 121 public void activate() {
122 + appId =
123 + coreService.registerApplication("org.onosproject.net.proxyarp");
124 +
105 deviceService.addListener(new InternalDeviceListener()); 125 deviceService.addListener(new InternalDeviceListener());
106 linkService.addListener(new InternalLinkListener()); 126 linkService.addListener(new InternalLinkListener());
107 determinePortLocations(); 127 determinePortLocations();
128 + pushRules();
129 +
108 log.info("Started"); 130 log.info("Started");
109 } 131 }
110 132
...@@ -396,6 +418,36 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -396,6 +418,36 @@ public class ProxyArpManager implements ProxyArpService {
396 return eth; 418 return eth;
397 } 419 }
398 420
421 + /**
422 + * Pushes flow rules to all devices.
423 + */
424 + private void pushRules() {
425 + for (Device device : deviceService.getDevices()) {
426 + pushRules(device);
427 + }
428 + }
429 +
430 + /**
431 + * Pushes flow rules to the device to receive control packets that need
432 + * to be processed.
433 + *
434 + * @param device the device to push the rules to
435 + */
436 + private synchronized void pushRules(Device device) {
437 + TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
438 + TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
439 +
440 + // Get all ARP packets
441 + sbuilder.matchEthType(Ethernet.TYPE_ARP);
442 + tbuilder.setOutput(PortNumber.CONTROLLER);
443 + FlowRule flowArp =
444 + new DefaultFlowRule(device.id(),
445 + sbuilder.build(), tbuilder.build(),
446 + FLOW_RULE_PRIORITY, appId, 0, true);
447 +
448 + flowRuleService.applyFlowRules(flowArp);
449 + }
450 +
399 public class InternalLinkListener implements LinkListener { 451 public class InternalLinkListener implements LinkListener {
400 452
401 @Override 453 @Override
...@@ -440,6 +492,8 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -440,6 +492,8 @@ public class ProxyArpManager implements ProxyArpService {
440 Device device = event.subject(); 492 Device device = event.subject();
441 switch (event.type()) { 493 switch (event.type()) {
442 case DEVICE_ADDED: 494 case DEVICE_ADDED:
495 + pushRules(device);
496 + break;
443 case DEVICE_AVAILABILITY_CHANGED: 497 case DEVICE_AVAILABILITY_CHANGED:
444 case DEVICE_SUSPENDED: 498 case DEVICE_SUSPENDED:
445 case DEVICE_UPDATED: 499 case DEVICE_UPDATED:
......
...@@ -18,6 +18,7 @@ package org.onosproject.net.proxyarp.impl; ...@@ -18,6 +18,7 @@ package org.onosproject.net.proxyarp.impl;
18 import static org.easymock.EasyMock.anyObject; 18 import static org.easymock.EasyMock.anyObject;
19 import static org.easymock.EasyMock.createMock; 19 import static org.easymock.EasyMock.createMock;
20 import static org.easymock.EasyMock.expect; 20 import static org.easymock.EasyMock.expect;
21 +import static org.easymock.EasyMock.expectLastCall;
21 import static org.easymock.EasyMock.replay; 22 import static org.easymock.EasyMock.replay;
22 import static org.junit.Assert.assertArrayEquals; 23 import static org.junit.Assert.assertArrayEquals;
23 import static org.junit.Assert.assertEquals; 24 import static org.junit.Assert.assertEquals;
...@@ -32,6 +33,9 @@ import java.util.Set; ...@@ -32,6 +33,9 @@ import java.util.Set;
32 33
33 import org.junit.Before; 34 import org.junit.Before;
34 import org.junit.Test; 35 import org.junit.Test;
36 +import org.onosproject.core.ApplicationId;
37 +import org.onosproject.core.CoreService;
38 +import org.onosproject.core.DefaultApplicationId;
35 import org.onosproject.net.ConnectPoint; 39 import org.onosproject.net.ConnectPoint;
36 import org.onosproject.net.DefaultHost; 40 import org.onosproject.net.DefaultHost;
37 import org.onosproject.net.Device; 41 import org.onosproject.net.Device;
...@@ -44,6 +48,8 @@ import org.onosproject.net.Port; ...@@ -44,6 +48,8 @@ import org.onosproject.net.Port;
44 import org.onosproject.net.PortNumber; 48 import org.onosproject.net.PortNumber;
45 import org.onosproject.net.device.DeviceListener; 49 import org.onosproject.net.device.DeviceListener;
46 import org.onosproject.net.device.DeviceService; 50 import org.onosproject.net.device.DeviceService;
51 +import org.onosproject.net.flow.FlowRule;
52 +import org.onosproject.net.flow.FlowRuleService;
47 import org.onosproject.net.flow.instructions.Instruction; 53 import org.onosproject.net.flow.instructions.Instruction;
48 import org.onosproject.net.flow.instructions.Instructions.OutputInstruction; 54 import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
49 import org.onosproject.net.host.HostService; 55 import org.onosproject.net.host.HostService;
...@@ -97,9 +103,13 @@ public class ProxyArpManagerTest { ...@@ -97,9 +103,13 @@ public class ProxyArpManagerTest {
97 103
98 private TestPacketService packetService; 104 private TestPacketService packetService;
99 105
106 + private CoreService coreService;
100 private DeviceService deviceService; 107 private DeviceService deviceService;
108 + private FlowRuleService flowRuleService;
101 private LinkService linkService; 109 private LinkService linkService;
102 private HostService hostService; 110 private HostService hostService;
111 + private ApplicationId appId = new DefaultApplicationId((short) 100,
112 + "org.onosproject.net.proxyarp");
103 113
104 @Before 114 @Before
105 public void setUp() throws Exception { 115 public void setUp() throws Exception {
...@@ -113,7 +123,9 @@ public class ProxyArpManagerTest { ...@@ -113,7 +123,9 @@ public class ProxyArpManagerTest {
113 proxyArp.hostService = hostService; 123 proxyArp.hostService = hostService;
114 124
115 createTopology(); 125 createTopology();
126 + proxyArp.coreService = coreService;
116 proxyArp.deviceService = deviceService; 127 proxyArp.deviceService = deviceService;
128 + proxyArp.flowRuleService = flowRuleService;
117 proxyArp.linkService = linkService; 129 proxyArp.linkService = linkService;
118 130
119 proxyArp.activate(); 131 proxyArp.activate();
...@@ -130,6 +142,16 @@ public class ProxyArpManagerTest { ...@@ -130,6 +142,16 @@ public class ProxyArpManagerTest {
130 * addresses configured. 142 * addresses configured.
131 */ 143 */
132 private void createTopology() { 144 private void createTopology() {
145 + coreService = createMock(CoreService.class);
146 + expect(coreService.registerApplication(appId.name()))
147 + .andReturn(appId).anyTimes();
148 + replay(coreService);
149 +
150 + flowRuleService = createMock(FlowRuleService.class);
151 + flowRuleService.applyFlowRules(anyObject(FlowRule.class));
152 + expectLastCall().anyTimes();
153 + replay(flowRuleService);
154 +
133 deviceService = createMock(DeviceService.class); 155 deviceService = createMock(DeviceService.class);
134 linkService = createMock(LinkService.class); 156 linkService = createMock(LinkService.class);
135 157
......
...@@ -52,6 +52,11 @@ ...@@ -52,6 +52,11 @@
52 <classifier>tests</classifier> 52 <classifier>tests</classifier>
53 <scope>test</scope> 53 <scope>test</scope>
54 </dependency> 54 </dependency>
55 + <dependency>
56 + <groupId>org.easymock</groupId>
57 + <artifactId>easymock</artifactId>
58 + <scope>test</scope>
59 + </dependency>
55 </dependencies> 60 </dependencies>
56 61
57 </project> 62 </project>
......
...@@ -22,14 +22,24 @@ import org.apache.felix.scr.annotations.Modified; ...@@ -22,14 +22,24 @@ import org.apache.felix.scr.annotations.Modified;
22 import org.apache.felix.scr.annotations.Property; 22 import org.apache.felix.scr.annotations.Property;
23 import org.apache.felix.scr.annotations.Reference; 23 import org.apache.felix.scr.annotations.Reference;
24 import org.apache.felix.scr.annotations.ReferenceCardinality; 24 import org.apache.felix.scr.annotations.ReferenceCardinality;
25 +import org.onosproject.core.ApplicationId;
26 +import org.onosproject.core.CoreService;
25 import org.onosproject.net.ConnectPoint; 27 import org.onosproject.net.ConnectPoint;
26 -import org.onosproject.net.DeviceId; 28 +import org.onosproject.net.Device;
27 import org.onosproject.net.Host; 29 import org.onosproject.net.Host;
28 import org.onosproject.net.HostId; 30 import org.onosproject.net.HostId;
29 import org.onosproject.net.HostLocation; 31 import org.onosproject.net.HostLocation;
32 +import org.onosproject.net.PortNumber;
30 import org.onosproject.net.device.DeviceEvent; 33 import org.onosproject.net.device.DeviceEvent;
31 import org.onosproject.net.device.DeviceListener; 34 import org.onosproject.net.device.DeviceListener;
32 import org.onosproject.net.device.DeviceService; 35 import org.onosproject.net.device.DeviceService;
36 +import org.onosproject.net.flow.DefaultFlowRule;
37 +import org.onosproject.net.flow.DefaultTrafficSelector;
38 +import org.onosproject.net.flow.DefaultTrafficTreatment;
39 +import org.onosproject.net.flow.FlowRule;
40 +import org.onosproject.net.flow.FlowRuleService;
41 +import org.onosproject.net.flow.TrafficSelector;
42 +import org.onosproject.net.flow.TrafficTreatment;
33 import org.onosproject.net.host.DefaultHostDescription; 43 import org.onosproject.net.host.DefaultHostDescription;
34 import org.onosproject.net.host.HostDescription; 44 import org.onosproject.net.host.HostDescription;
35 import org.onosproject.net.host.HostProvider; 45 import org.onosproject.net.host.HostProvider;
...@@ -64,6 +74,14 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid ...@@ -64,6 +74,14 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid
64 74
65 private final Logger log = getLogger(getClass()); 75 private final Logger log = getLogger(getClass());
66 76
77 + private static final int FLOW_RULE_PRIORITY = 40000;
78 +
79 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
80 + protected CoreService coreService;
81 +
82 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
83 + protected FlowRuleService flowRuleService;
84 +
67 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 85 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
68 protected HostProviderRegistry providerRegistry; 86 protected HostProviderRegistry providerRegistry;
69 87
...@@ -84,6 +102,8 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid ...@@ -84,6 +102,8 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid
84 private final InternalHostProvider processor = new InternalHostProvider(); 102 private final InternalHostProvider processor = new InternalHostProvider();
85 private final DeviceListener deviceListener = new InternalDeviceListener(); 103 private final DeviceListener deviceListener = new InternalDeviceListener();
86 104
105 + private ApplicationId appId;
106 +
87 @Property(name = "hostRemovalEnabled", boolValue = true, 107 @Property(name = "hostRemovalEnabled", boolValue = true,
88 label = "Enable host removal on port/device down events") 108 label = "Enable host removal on port/device down events")
89 private boolean hostRemovalEnabled = true; 109 private boolean hostRemovalEnabled = true;
...@@ -98,10 +118,15 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid ...@@ -98,10 +118,15 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid
98 118
99 @Activate 119 @Activate
100 public void activate(ComponentContext context) { 120 public void activate(ComponentContext context) {
121 + appId =
122 + coreService.registerApplication("org.onosproject.provider.host");
123 +
101 modified(context); 124 modified(context);
102 providerService = providerRegistry.register(this); 125 providerService = providerRegistry.register(this);
103 pktService.addProcessor(processor, 1); 126 pktService.addProcessor(processor, 1);
104 deviceService.addListener(deviceListener); 127 deviceService.addListener(deviceListener);
128 + pushRules();
129 +
105 log.info("Started"); 130 log.info("Started");
106 } 131 }
107 132
...@@ -133,6 +158,36 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid ...@@ -133,6 +158,36 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid
133 log.info("Triggering probe on device {}", host); 158 log.info("Triggering probe on device {}", host);
134 } 159 }
135 160
161 + /**
162 + * Pushes flow rules to all devices.
163 + */
164 + private void pushRules() {
165 + for (Device device : deviceService.getDevices()) {
166 + pushRules(device);
167 + }
168 + }
169 +
170 + /**
171 + * Pushes flow rules to the device to receive control packets that need
172 + * to be processed.
173 + *
174 + * @param device the device to push the rules to
175 + */
176 + private synchronized void pushRules(Device device) {
177 + TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
178 + TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
179 +
180 + // Get all ARP packets
181 + sbuilder.matchEthType(Ethernet.TYPE_ARP);
182 + tbuilder.setOutput(PortNumber.CONTROLLER);
183 + FlowRule flowArp =
184 + new DefaultFlowRule(device.id(),
185 + sbuilder.build(), tbuilder.build(),
186 + FLOW_RULE_PRIORITY, appId, 0, true);
187 +
188 + flowRuleService.applyFlowRules(flowArp);
189 + }
190 +
136 private class InternalHostProvider implements PacketProcessor { 191 private class InternalHostProvider implements PacketProcessor {
137 192
138 @Override 193 @Override
...@@ -179,23 +234,40 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid ...@@ -179,23 +234,40 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid
179 private class InternalDeviceListener implements DeviceListener { 234 private class InternalDeviceListener implements DeviceListener {
180 @Override 235 @Override
181 public void event(DeviceEvent event) { 236 public void event(DeviceEvent event) {
182 - if (!hostRemovalEnabled) { 237 + Device device = event.subject();
183 - return; 238 + switch (event.type()) {
184 - } 239 + case DEVICE_ADDED:
185 - 240 + pushRules(device);
186 - DeviceEvent.Type type = event.type(); 241 + break;
187 - DeviceId deviceId = event.subject().id(); 242 + case DEVICE_AVAILABILITY_CHANGED:
188 - if (type == DeviceEvent.Type.PORT_UPDATED) { 243 + if (hostRemovalEnabled &&
189 - ConnectPoint point = new ConnectPoint(deviceId, event.port().number()); 244 + !deviceService.isAvailable(device.id())) {
190 - removeHosts(hostService.getConnectedHosts(point)); 245 + removeHosts(hostService.getConnectedHosts(device.id()));
191 -
192 - } else if (type == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED) {
193 - if (!deviceService.isAvailable(deviceId)) {
194 - removeHosts(hostService.getConnectedHosts(deviceId));
195 } 246 }
196 - 247 + break;
197 - } else if (type == DeviceEvent.Type.DEVICE_REMOVED) { 248 + case DEVICE_SUSPENDED:
198 - removeHosts(hostService.getConnectedHosts(deviceId)); 249 + case DEVICE_UPDATED:
250 + // Nothing to do?
251 + break;
252 + case DEVICE_REMOVED:
253 + if (hostRemovalEnabled) {
254 + removeHosts(hostService.getConnectedHosts(device.id()));
255 + }
256 + break;
257 + case PORT_ADDED:
258 + break;
259 + case PORT_UPDATED:
260 + if (hostRemovalEnabled) {
261 + ConnectPoint point =
262 + new ConnectPoint(device.id(), event.port().number());
263 + removeHosts(hostService.getConnectedHosts(point));
264 + }
265 + break;
266 + case PORT_REMOVED:
267 + // Nothing to do?
268 + break;
269 + default:
270 + break;
199 } 271 }
200 } 272 }
201 } 273 }
......
...@@ -15,10 +15,19 @@ ...@@ -15,10 +15,19 @@
15 */ 15 */
16 package org.onosproject.provider.host.impl; 16 package org.onosproject.provider.host.impl;
17 17
18 +import static org.easymock.EasyMock.anyObject;
19 +import static org.easymock.EasyMock.createMock;
20 +import static org.easymock.EasyMock.expect;
21 +import static org.easymock.EasyMock.expectLastCall;
22 +import static org.easymock.EasyMock.replay;
23 +
18 import com.google.common.collect.ImmutableSet; 24 import com.google.common.collect.ImmutableSet;
19 import org.junit.After; 25 import org.junit.After;
20 import org.junit.Before; 26 import org.junit.Before;
21 import org.junit.Test; 27 import org.junit.Test;
28 +import org.onosproject.core.ApplicationId;
29 +import org.onosproject.core.CoreService;
30 +import org.onosproject.core.DefaultApplicationId;
22 import org.onosproject.net.ConnectPoint; 31 import org.onosproject.net.ConnectPoint;
23 import org.onosproject.net.DefaultDevice; 32 import org.onosproject.net.DefaultDevice;
24 import org.onosproject.net.DefaultHost; 33 import org.onosproject.net.DefaultHost;
...@@ -31,6 +40,8 @@ import org.onosproject.net.HostLocation; ...@@ -31,6 +40,8 @@ import org.onosproject.net.HostLocation;
31 import org.onosproject.net.device.DeviceEvent; 40 import org.onosproject.net.device.DeviceEvent;
32 import org.onosproject.net.device.DeviceListener; 41 import org.onosproject.net.device.DeviceListener;
33 import org.onosproject.net.device.DeviceServiceAdapter; 42 import org.onosproject.net.device.DeviceServiceAdapter;
43 +import org.onosproject.net.flow.FlowRule;
44 +import org.onosproject.net.flow.FlowRuleService;
34 import org.onosproject.net.flow.TrafficTreatment; 45 import org.onosproject.net.flow.TrafficTreatment;
35 import org.onosproject.net.host.HostDescription; 46 import org.onosproject.net.host.HostDescription;
36 import org.onosproject.net.host.HostProvider; 47 import org.onosproject.net.host.HostProvider;
...@@ -56,6 +67,7 @@ import org.onlab.packet.MacAddress; ...@@ -56,6 +67,7 @@ import org.onlab.packet.MacAddress;
56 import org.onlab.packet.VlanId; 67 import org.onlab.packet.VlanId;
57 68
58 import java.nio.ByteBuffer; 69 import java.nio.ByteBuffer;
70 +import java.util.Collections;
59 import java.util.Dictionary; 71 import java.util.Dictionary;
60 import java.util.Hashtable; 72 import java.util.Hashtable;
61 import java.util.Set; 73 import java.util.Set;
...@@ -118,10 +130,29 @@ public class HostLocationProviderTest { ...@@ -118,10 +130,29 @@ public class HostLocationProviderTest {
118 private final TestPacketService packetService = new TestPacketService(); 130 private final TestPacketService packetService = new TestPacketService();
119 131
120 private PacketProcessor testProcessor; 132 private PacketProcessor testProcessor;
133 + private CoreService coreService;
134 + private FlowRuleService flowRuleService;
121 private TestHostProviderService providerService; 135 private TestHostProviderService providerService;
122 136
137 + private ApplicationId appId = new DefaultApplicationId((short) 100,
138 + "org.onosproject.provider.host");
139 +
123 @Before 140 @Before
124 public void setUp() { 141 public void setUp() {
142 +
143 + coreService = createMock(CoreService.class);
144 + expect(coreService.registerApplication(appId.name()))
145 + .andReturn(appId).anyTimes();
146 + replay(coreService);
147 +
148 + flowRuleService = createMock(FlowRuleService.class);
149 + flowRuleService.applyFlowRules(anyObject(FlowRule.class));
150 + expectLastCall().anyTimes();
151 + replay(flowRuleService);
152 +
153 + provider.coreService = coreService;
154 + provider.flowRuleService = flowRuleService;
155 +
125 provider.providerRegistry = hostRegistry; 156 provider.providerRegistry = hostRegistry;
126 provider.topologyService = topoService; 157 provider.topologyService = topoService;
127 provider.pktService = packetService; 158 provider.pktService = packetService;
...@@ -189,8 +220,9 @@ public class HostLocationProviderTest { ...@@ -189,8 +220,9 @@ public class HostLocationProviderTest {
189 @After 220 @After
190 public void tearDown() { 221 public void tearDown() {
191 provider.deactivate(); 222 provider.deactivate();
223 + provider.coreService = null;
224 + provider.flowRuleService = null;
192 provider.providerRegistry = null; 225 provider.providerRegistry = null;
193 -
194 } 226 }
195 227
196 private class TestHostRegistry implements HostProviderRegistry { 228 private class TestHostRegistry implements HostProviderRegistry {
...@@ -339,6 +371,11 @@ public class HostLocationProviderTest { ...@@ -339,6 +371,11 @@ public class HostLocationProviderTest {
339 public void addListener(DeviceListener listener) { 371 public void addListener(DeviceListener listener) {
340 this.listener = listener; 372 this.listener = listener;
341 } 373 }
374 +
375 + @Override
376 + public Iterable<Device> getDevices() {
377 + return Collections.emptyList();
378 + }
342 } 379 }
343 380
344 private class TestHostService extends HostServiceAdapter { 381 private class TestHostService extends HostServiceAdapter {
......
...@@ -39,5 +39,12 @@ ...@@ -39,5 +39,12 @@
39 <classifier>tests</classifier> 39 <classifier>tests</classifier>
40 <scope>test</scope> 40 <scope>test</scope>
41 </dependency> 41 </dependency>
42 +
43 + <dependency>
44 + <groupId>org.easymock</groupId>
45 + <artifactId>easymock</artifactId>
46 + <scope>test</scope>
47 + </dependency>
48 +
42 </dependencies> 49 </dependencies>
43 </project> 50 </project>
......
...@@ -20,6 +20,9 @@ import org.apache.felix.scr.annotations.Component; ...@@ -20,6 +20,9 @@ import org.apache.felix.scr.annotations.Component;
20 import org.apache.felix.scr.annotations.Deactivate; 20 import org.apache.felix.scr.annotations.Deactivate;
21 import org.apache.felix.scr.annotations.Reference; 21 import org.apache.felix.scr.annotations.Reference;
22 import org.apache.felix.scr.annotations.ReferenceCardinality; 22 import org.apache.felix.scr.annotations.ReferenceCardinality;
23 +import org.onlab.packet.Ethernet;
24 +import org.onosproject.core.ApplicationId;
25 +import org.onosproject.core.CoreService;
23 import org.onosproject.mastership.MastershipEvent; 26 import org.onosproject.mastership.MastershipEvent;
24 import org.onosproject.mastership.MastershipListener; 27 import org.onosproject.mastership.MastershipListener;
25 import org.onosproject.mastership.MastershipService; 28 import org.onosproject.mastership.MastershipService;
...@@ -27,9 +30,17 @@ import org.onosproject.net.ConnectPoint; ...@@ -27,9 +30,17 @@ import org.onosproject.net.ConnectPoint;
27 import org.onosproject.net.Device; 30 import org.onosproject.net.Device;
28 import org.onosproject.net.DeviceId; 31 import org.onosproject.net.DeviceId;
29 import org.onosproject.net.Port; 32 import org.onosproject.net.Port;
33 +import org.onosproject.net.PortNumber;
30 import org.onosproject.net.device.DeviceEvent; 34 import org.onosproject.net.device.DeviceEvent;
31 import org.onosproject.net.device.DeviceListener; 35 import org.onosproject.net.device.DeviceListener;
32 import org.onosproject.net.device.DeviceService; 36 import org.onosproject.net.device.DeviceService;
37 +import org.onosproject.net.flow.DefaultFlowRule;
38 +import org.onosproject.net.flow.DefaultTrafficSelector;
39 +import org.onosproject.net.flow.DefaultTrafficTreatment;
40 +import org.onosproject.net.flow.FlowRule;
41 +import org.onosproject.net.flow.FlowRuleService;
42 +import org.onosproject.net.flow.TrafficSelector;
43 +import org.onosproject.net.flow.TrafficTreatment;
33 import org.onosproject.net.link.LinkProvider; 44 import org.onosproject.net.link.LinkProvider;
34 import org.onosproject.net.link.LinkProviderRegistry; 45 import org.onosproject.net.link.LinkProviderRegistry;
35 import org.onosproject.net.link.LinkProviderService; 46 import org.onosproject.net.link.LinkProviderService;
...@@ -59,6 +70,14 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -59,6 +70,14 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
59 70
60 private final Logger log = getLogger(getClass()); 71 private final Logger log = getLogger(getClass());
61 72
73 + private static final int FLOW_RULE_PRIORITY = 40000;
74 +
75 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
76 + protected CoreService coreService;
77 +
78 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
79 + protected FlowRuleService flowRuleService;
80 +
62 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 81 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
63 protected LinkProviderRegistry providerRegistry; 82 protected LinkProviderRegistry providerRegistry;
64 83
...@@ -86,6 +105,8 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -86,6 +105,8 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
86 105
87 protected final Map<DeviceId, LinkDiscovery> discoverers = new ConcurrentHashMap<>(); 106 protected final Map<DeviceId, LinkDiscovery> discoverers = new ConcurrentHashMap<>();
88 107
108 + private ApplicationId appId;
109 +
89 /** 110 /**
90 * Creates an OpenFlow link provider. 111 * Creates an OpenFlow link provider.
91 */ 112 */
...@@ -95,6 +116,9 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -95,6 +116,9 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
95 116
96 @Activate 117 @Activate
97 public void activate() { 118 public void activate() {
119 + appId =
120 + coreService.registerApplication("org.onosproject.provider.lldp");
121 +
98 providerService = providerRegistry.register(this); 122 providerService = providerRegistry.register(this);
99 deviceService.addListener(listener); 123 deviceService.addListener(listener);
100 packetSevice.addProcessor(listener, 0); 124 packetSevice.addProcessor(listener, 0);
...@@ -116,6 +140,8 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -116,6 +140,8 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
116 executor.scheduleAtFixedRate(new SyncDeviceInfoTask(), INIT_DELAY, 140 executor.scheduleAtFixedRate(new SyncDeviceInfoTask(), INIT_DELAY,
117 DELAY, TimeUnit.SECONDS); 141 DELAY, TimeUnit.SECONDS);
118 142
143 + pushRules();
144 +
119 log.info("Started"); 145 log.info("Started");
120 } 146 }
121 147
...@@ -134,6 +160,48 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -134,6 +160,48 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
134 log.info("Stopped"); 160 log.info("Stopped");
135 } 161 }
136 162
163 + /**
164 + * Pushes flow rules to all devices.
165 + */
166 + private void pushRules() {
167 + for (Device device : deviceService.getDevices()) {
168 + pushRules(device);
169 + }
170 + }
171 +
172 + /**
173 + * Pushes flow rules to the device to receive control packets that need
174 + * to be processed.
175 + *
176 + * @param device the device to push the rules to
177 + */
178 + private synchronized void pushRules(Device device) {
179 + TrafficSelector.Builder sbuilder;
180 + TrafficTreatment.Builder tbuilder;
181 +
182 + // Get all LLDP packets
183 + sbuilder = DefaultTrafficSelector.builder();
184 + tbuilder = DefaultTrafficTreatment.builder();
185 + sbuilder.matchEthType(Ethernet.TYPE_LLDP);
186 + tbuilder.setOutput(PortNumber.CONTROLLER);
187 + FlowRule flowLldp =
188 + new DefaultFlowRule(device.id(),
189 + sbuilder.build(), tbuilder.build(),
190 + FLOW_RULE_PRIORITY, appId, 0, true);
191 +
192 + // Get all BDDP packets
193 + sbuilder = DefaultTrafficSelector.builder();
194 + tbuilder = DefaultTrafficTreatment.builder();
195 + sbuilder.matchEthType(Ethernet.TYPE_BSN);
196 + tbuilder.setOutput(PortNumber.CONTROLLER);
197 + FlowRule flowBddp =
198 + new DefaultFlowRule(device.id(),
199 + sbuilder.build(), tbuilder.build(),
200 + FLOW_RULE_PRIORITY, appId, 0, true);
201 +
202 + flowRuleService.applyFlowRules(flowLldp, flowBddp);
203 + }
204 +
137 private class InternalRoleListener implements MastershipListener { 205 private class InternalRoleListener implements MastershipListener {
138 206
139 @Override 207 @Override
...@@ -179,6 +247,8 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -179,6 +247,8 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
179 final DeviceId deviceId = device.id(); 247 final DeviceId deviceId = device.id();
180 switch (event.type()) { 248 switch (event.type()) {
181 case DEVICE_ADDED: 249 case DEVICE_ADDED:
250 + pushRules(device);
251 + // FALLTHROUGH
182 case DEVICE_UPDATED: 252 case DEVICE_UPDATED:
183 synchronized (discoverers) { 253 synchronized (discoverers) {
184 ld = discoverers.get(deviceId); 254 ld = discoverers.get(deviceId);
......
...@@ -15,6 +15,11 @@ ...@@ -15,6 +15,11 @@
15 */ 15 */
16 package org.onosproject.provider.lldp.impl; 16 package org.onosproject.provider.lldp.impl;
17 17
18 +import static org.easymock.EasyMock.anyObject;
19 +import static org.easymock.EasyMock.createMock;
20 +import static org.easymock.EasyMock.expect;
21 +import static org.easymock.EasyMock.expectLastCall;
22 +import static org.easymock.EasyMock.replay;
18 23
19 import com.google.common.collect.ArrayListMultimap; 24 import com.google.common.collect.ArrayListMultimap;
20 import com.google.common.collect.Lists; 25 import com.google.common.collect.Lists;
...@@ -25,6 +30,9 @@ import org.junit.Before; ...@@ -25,6 +30,9 @@ import org.junit.Before;
25 import org.junit.Test; 30 import org.junit.Test;
26 import org.onosproject.cluster.NodeId; 31 import org.onosproject.cluster.NodeId;
27 import org.onosproject.cluster.RoleInfo; 32 import org.onosproject.cluster.RoleInfo;
33 +import org.onosproject.core.ApplicationId;
34 +import org.onosproject.core.CoreService;
35 +import org.onosproject.core.DefaultApplicationId;
28 import org.onosproject.mastership.MastershipListener; 36 import org.onosproject.mastership.MastershipListener;
29 import org.onosproject.mastership.MastershipService; 37 import org.onosproject.mastership.MastershipService;
30 import org.onosproject.net.ConnectPoint; 38 import org.onosproject.net.ConnectPoint;
...@@ -38,6 +46,8 @@ import org.onosproject.net.PortNumber; ...@@ -38,6 +46,8 @@ import org.onosproject.net.PortNumber;
38 import org.onosproject.net.device.DeviceEvent; 46 import org.onosproject.net.device.DeviceEvent;
39 import org.onosproject.net.device.DeviceListener; 47 import org.onosproject.net.device.DeviceListener;
40 import org.onosproject.net.device.DeviceServiceAdapter; 48 import org.onosproject.net.device.DeviceServiceAdapter;
49 +import org.onosproject.net.flow.FlowRule;
50 +import org.onosproject.net.flow.FlowRuleService;
41 import org.onosproject.net.flow.TrafficTreatment; 51 import org.onosproject.net.flow.TrafficTreatment;
42 import org.onosproject.net.link.LinkDescription; 52 import org.onosproject.net.link.LinkDescription;
43 import org.onosproject.net.link.LinkProvider; 53 import org.onosproject.net.link.LinkProvider;
...@@ -80,14 +90,33 @@ public class LLDPLinkProviderTest { ...@@ -80,14 +90,33 @@ public class LLDPLinkProviderTest {
80 private final TestDeviceService deviceService = new TestDeviceService(); 90 private final TestDeviceService deviceService = new TestDeviceService();
81 private final TestMasterShipService masterService = new TestMasterShipService(); 91 private final TestMasterShipService masterService = new TestMasterShipService();
82 92
93 + private CoreService coreService;
94 + private FlowRuleService flowRuleService;
83 private TestLinkProviderService providerService; 95 private TestLinkProviderService providerService;
84 96
85 private PacketProcessor testProcessor; 97 private PacketProcessor testProcessor;
86 private DeviceListener deviceListener; 98 private DeviceListener deviceListener;
87 99
100 + private ApplicationId appId = new DefaultApplicationId((short) 100,
101 + "org.onosproject.provider.lldp");
102 +
88 @Before 103 @Before
89 public void setUp() { 104 public void setUp() {
90 105
106 + coreService = createMock(CoreService.class);
107 + expect(coreService.registerApplication(appId.name()))
108 + .andReturn(appId).anyTimes();
109 + replay(coreService);
110 +
111 + flowRuleService = createMock(FlowRuleService.class);
112 + flowRuleService.applyFlowRules(anyObject(FlowRule.class),
113 + anyObject(FlowRule.class));
114 + expectLastCall().anyTimes();
115 + replay(flowRuleService);
116 +
117 + provider.coreService = coreService;
118 + provider.flowRuleService = flowRuleService;
119 +
91 provider.deviceService = deviceService; 120 provider.deviceService = deviceService;
92 provider.packetSevice = packetService; 121 provider.packetSevice = packetService;
93 provider.providerRegistry = linkService; 122 provider.providerRegistry = linkService;
...@@ -178,6 +207,8 @@ public class LLDPLinkProviderTest { ...@@ -178,6 +207,8 @@ public class LLDPLinkProviderTest {
178 @After 207 @After
179 public void tearDown() { 208 public void tearDown() {
180 provider.deactivate(); 209 provider.deactivate();
210 + provider.coreService = null;
211 + provider.flowRuleService = null;
181 provider.providerRegistry = null; 212 provider.providerRegistry = null;
182 provider.deviceService = null; 213 provider.deviceService = null;
183 provider.packetSevice = null; 214 provider.packetSevice = null;
......