Pavlin Radoslavov
Committed by Gerrit Code Review

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

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.punt();
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,23 @@ import org.apache.felix.scr.annotations.Modified; ...@@ -22,14 +22,23 @@ 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;
30 import org.onosproject.net.device.DeviceEvent; 32 import org.onosproject.net.device.DeviceEvent;
31 import org.onosproject.net.device.DeviceListener; 33 import org.onosproject.net.device.DeviceListener;
32 import org.onosproject.net.device.DeviceService; 34 import org.onosproject.net.device.DeviceService;
35 +import org.onosproject.net.flow.DefaultFlowRule;
36 +import org.onosproject.net.flow.DefaultTrafficSelector;
37 +import org.onosproject.net.flow.DefaultTrafficTreatment;
38 +import org.onosproject.net.flow.FlowRule;
39 +import org.onosproject.net.flow.FlowRuleService;
40 +import org.onosproject.net.flow.TrafficSelector;
41 +import org.onosproject.net.flow.TrafficTreatment;
33 import org.onosproject.net.host.DefaultHostDescription; 42 import org.onosproject.net.host.DefaultHostDescription;
34 import org.onosproject.net.host.HostDescription; 43 import org.onosproject.net.host.HostDescription;
35 import org.onosproject.net.host.HostProvider; 44 import org.onosproject.net.host.HostProvider;
...@@ -68,6 +77,14 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid ...@@ -68,6 +77,14 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid
68 77
69 private final Logger log = getLogger(getClass()); 78 private final Logger log = getLogger(getClass());
70 79
80 + private static final int FLOW_RULE_PRIORITY = 40000;
81 +
82 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
83 + protected CoreService coreService;
84 +
85 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
86 + protected FlowRuleService flowRuleService;
87 +
71 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 88 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
72 protected HostProviderRegistry providerRegistry; 89 protected HostProviderRegistry providerRegistry;
73 90
...@@ -88,6 +105,8 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid ...@@ -88,6 +105,8 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid
88 private final InternalHostProvider processor = new InternalHostProvider(); 105 private final InternalHostProvider processor = new InternalHostProvider();
89 private final DeviceListener deviceListener = new InternalDeviceListener(); 106 private final DeviceListener deviceListener = new InternalDeviceListener();
90 107
108 + private ApplicationId appId;
109 +
91 @Property(name = "hostRemovalEnabled", boolValue = true, 110 @Property(name = "hostRemovalEnabled", boolValue = true,
92 label = "Enable host removal on port/device down events") 111 label = "Enable host removal on port/device down events")
93 private boolean hostRemovalEnabled = true; 112 private boolean hostRemovalEnabled = true;
...@@ -102,10 +121,15 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid ...@@ -102,10 +121,15 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid
102 121
103 @Activate 122 @Activate
104 public void activate(ComponentContext context) { 123 public void activate(ComponentContext context) {
124 + appId =
125 + coreService.registerApplication("org.onosproject.provider.host");
126 +
105 modified(context); 127 modified(context);
106 providerService = providerRegistry.register(this); 128 providerService = providerRegistry.register(this);
107 pktService.addProcessor(processor, 1); 129 pktService.addProcessor(processor, 1);
108 deviceService.addListener(deviceListener); 130 deviceService.addListener(deviceListener);
131 + pushRules();
132 +
109 log.info("Started"); 133 log.info("Started");
110 } 134 }
111 135
...@@ -137,6 +161,36 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid ...@@ -137,6 +161,36 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid
137 log.info("Triggering probe on device {}", host); 161 log.info("Triggering probe on device {}", host);
138 } 162 }
139 163
164 + /**
165 + * Pushes flow rules to all devices.
166 + */
167 + private void pushRules() {
168 + for (Device device : deviceService.getDevices()) {
169 + pushRules(device);
170 + }
171 + }
172 +
173 + /**
174 + * Pushes flow rules to the device to receive control packets that need
175 + * to be processed.
176 + *
177 + * @param device the device to push the rules to
178 + */
179 + private synchronized void pushRules(Device device) {
180 + TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
181 + TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
182 +
183 + // Get all ARP packets
184 + sbuilder.matchEthType(Ethernet.TYPE_ARP);
185 + tbuilder.punt();
186 + FlowRule flowArp =
187 + new DefaultFlowRule(device.id(),
188 + sbuilder.build(), tbuilder.build(),
189 + FLOW_RULE_PRIORITY, appId, 0, true);
190 +
191 + flowRuleService.applyFlowRules(flowArp);
192 + }
193 +
140 private class InternalHostProvider implements PacketProcessor { 194 private class InternalHostProvider implements PacketProcessor {
141 195
142 @Override 196 @Override
...@@ -204,23 +258,40 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid ...@@ -204,23 +258,40 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid
204 private class InternalDeviceListener implements DeviceListener { 258 private class InternalDeviceListener implements DeviceListener {
205 @Override 259 @Override
206 public void event(DeviceEvent event) { 260 public void event(DeviceEvent event) {
207 - if (!hostRemovalEnabled) { 261 + Device device = event.subject();
208 - return; 262 + switch (event.type()) {
209 - } 263 + case DEVICE_ADDED:
210 - 264 + pushRules(device);
211 - DeviceEvent.Type type = event.type(); 265 + break;
212 - DeviceId deviceId = event.subject().id(); 266 + case DEVICE_AVAILABILITY_CHANGED:
213 - if (type == DeviceEvent.Type.PORT_UPDATED) { 267 + if (hostRemovalEnabled &&
214 - ConnectPoint point = new ConnectPoint(deviceId, event.port().number()); 268 + !deviceService.isAvailable(device.id())) {
215 - removeHosts(hostService.getConnectedHosts(point)); 269 + removeHosts(hostService.getConnectedHosts(device.id()));
216 -
217 - } else if (type == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED) {
218 - if (!deviceService.isAvailable(deviceId)) {
219 - removeHosts(hostService.getConnectedHosts(deviceId));
220 } 270 }
221 - 271 + break;
222 - } else if (type == DeviceEvent.Type.DEVICE_REMOVED) { 272 + case DEVICE_SUSPENDED:
223 - removeHosts(hostService.getConnectedHosts(deviceId)); 273 + case DEVICE_UPDATED:
274 + // Nothing to do?
275 + break;
276 + case DEVICE_REMOVED:
277 + if (hostRemovalEnabled) {
278 + removeHosts(hostService.getConnectedHosts(device.id()));
279 + }
280 + break;
281 + case PORT_ADDED:
282 + break;
283 + case PORT_UPDATED:
284 + if (hostRemovalEnabled) {
285 + ConnectPoint point =
286 + new ConnectPoint(device.id(), event.port().number());
287 + removeHosts(hostService.getConnectedHosts(point));
288 + }
289 + break;
290 + case PORT_REMOVED:
291 + // Nothing to do?
292 + break;
293 + default:
294 + break;
224 } 295 }
225 } 296 }
226 } 297 }
......
...@@ -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 {
......
...@@ -44,5 +44,12 @@ ...@@ -44,5 +44,12 @@
44 <classifier>tests</classifier> 44 <classifier>tests</classifier>
45 <scope>test</scope> 45 <scope>test</scope>
46 </dependency> 46 </dependency>
47 +
48 + <dependency>
49 + <groupId>org.easymock</groupId>
50 + <artifactId>easymock</artifactId>
51 + <scope>test</scope>
52 + </dependency>
53 +
47 </dependencies> 54 </dependencies>
48 </project> 55 </project>
......
...@@ -22,6 +22,9 @@ import org.apache.felix.scr.annotations.Modified; ...@@ -22,6 +22,9 @@ 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.onlab.packet.Ethernet;
26 +import org.onosproject.core.ApplicationId;
27 +import org.onosproject.core.CoreService;
25 import org.onosproject.mastership.MastershipEvent; 28 import org.onosproject.mastership.MastershipEvent;
26 import org.onosproject.mastership.MastershipListener; 29 import org.onosproject.mastership.MastershipListener;
27 import org.onosproject.mastership.MastershipService; 30 import org.onosproject.mastership.MastershipService;
...@@ -32,6 +35,13 @@ import org.onosproject.net.Port; ...@@ -32,6 +35,13 @@ import org.onosproject.net.Port;
32 import org.onosproject.net.device.DeviceEvent; 35 import org.onosproject.net.device.DeviceEvent;
33 import org.onosproject.net.device.DeviceListener; 36 import org.onosproject.net.device.DeviceListener;
34 import org.onosproject.net.device.DeviceService; 37 import org.onosproject.net.device.DeviceService;
38 +import org.onosproject.net.flow.DefaultFlowRule;
39 +import org.onosproject.net.flow.DefaultTrafficSelector;
40 +import org.onosproject.net.flow.DefaultTrafficTreatment;
41 +import org.onosproject.net.flow.FlowRule;
42 +import org.onosproject.net.flow.FlowRuleService;
43 +import org.onosproject.net.flow.TrafficSelector;
44 +import org.onosproject.net.flow.TrafficTreatment;
35 import org.onosproject.net.link.LinkProvider; 45 import org.onosproject.net.link.LinkProvider;
36 import org.onosproject.net.link.LinkProviderRegistry; 46 import org.onosproject.net.link.LinkProviderRegistry;
37 import org.onosproject.net.link.LinkProviderService; 47 import org.onosproject.net.link.LinkProviderService;
...@@ -67,7 +77,6 @@ import static org.slf4j.LoggerFactory.getLogger; ...@@ -67,7 +77,6 @@ import static org.slf4j.LoggerFactory.getLogger;
67 @Component(immediate = true) 77 @Component(immediate = true)
68 public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { 78 public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
69 79
70 -
71 private static final String PROP_USE_BDDP = "useBDDP"; 80 private static final String PROP_USE_BDDP = "useBDDP";
72 81
73 private static final String PROP_LLDP_SUPPRESSION = "lldpSuppression"; 82 private static final String PROP_LLDP_SUPPRESSION = "lldpSuppression";
...@@ -76,6 +85,14 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -76,6 +85,14 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
76 85
77 private final Logger log = getLogger(getClass()); 86 private final Logger log = getLogger(getClass());
78 87
88 + private static final int FLOW_RULE_PRIORITY = 40000;
89 +
90 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
91 + protected CoreService coreService;
92 +
93 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
94 + protected FlowRuleService flowRuleService;
95 +
79 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 96 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
80 protected LinkProviderRegistry providerRegistry; 97 protected LinkProviderRegistry providerRegistry;
81 98
...@@ -111,6 +128,7 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -111,6 +128,7 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
111 protected final Map<DeviceId, LinkDiscovery> discoverers = new ConcurrentHashMap<>(); 128 protected final Map<DeviceId, LinkDiscovery> discoverers = new ConcurrentHashMap<>();
112 129
113 private SuppressionRules rules; 130 private SuppressionRules rules;
131 + private ApplicationId appId;
114 132
115 /** 133 /**
116 * Creates an OpenFlow link provider. 134 * Creates an OpenFlow link provider.
...@@ -121,6 +139,9 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -121,6 +139,9 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
121 139
122 @Activate 140 @Activate
123 public void activate() { 141 public void activate() {
142 + appId =
143 + coreService.registerApplication("org.onosproject.provider.lldp");
144 +
124 loadSuppressionRules(); 145 loadSuppressionRules();
125 146
126 providerService = providerRegistry.register(this); 147 providerService = providerRegistry.register(this);
...@@ -153,6 +174,8 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -153,6 +174,8 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
153 executor.scheduleAtFixedRate(new SyncDeviceInfoTask(), INIT_DELAY, 174 executor.scheduleAtFixedRate(new SyncDeviceInfoTask(), INIT_DELAY,
154 DELAY, TimeUnit.SECONDS); 175 DELAY, TimeUnit.SECONDS);
155 176
177 + pushRules();
178 +
156 log.info("Started"); 179 log.info("Started");
157 } 180 }
158 181
...@@ -210,6 +233,48 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -210,6 +233,48 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
210 // should refresh discoverers when we need dynamic reconfiguration 233 // should refresh discoverers when we need dynamic reconfiguration
211 } 234 }
212 235
236 + /**
237 + * Pushes flow rules to all devices.
238 + */
239 + private void pushRules() {
240 + for (Device device : deviceService.getDevices()) {
241 + pushRules(device);
242 + }
243 + }
244 +
245 + /**
246 + * Pushes flow rules to the device to receive control packets that need
247 + * to be processed.
248 + *
249 + * @param device the device to push the rules to
250 + */
251 + private synchronized void pushRules(Device device) {
252 + TrafficSelector.Builder sbuilder;
253 + TrafficTreatment.Builder tbuilder;
254 +
255 + // Get all LLDP packets
256 + sbuilder = DefaultTrafficSelector.builder();
257 + tbuilder = DefaultTrafficTreatment.builder();
258 + sbuilder.matchEthType(Ethernet.TYPE_LLDP);
259 + tbuilder.punt();
260 + FlowRule flowLldp =
261 + new DefaultFlowRule(device.id(),
262 + sbuilder.build(), tbuilder.build(),
263 + FLOW_RULE_PRIORITY, appId, 0, true);
264 +
265 + // Get all BDDP packets
266 + sbuilder = DefaultTrafficSelector.builder();
267 + tbuilder = DefaultTrafficTreatment.builder();
268 + sbuilder.matchEthType(Ethernet.TYPE_BSN);
269 + tbuilder.punt();
270 + FlowRule flowBddp =
271 + new DefaultFlowRule(device.id(),
272 + sbuilder.build(), tbuilder.build(),
273 + FLOW_RULE_PRIORITY, appId, 0, true);
274 +
275 + flowRuleService.applyFlowRules(flowLldp, flowBddp);
276 + }
277 +
213 private class InternalRoleListener implements MastershipListener { 278 private class InternalRoleListener implements MastershipListener {
214 279
215 @Override 280 @Override
...@@ -258,6 +323,8 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider { ...@@ -258,6 +323,8 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
258 final DeviceId deviceId = device.id(); 323 final DeviceId deviceId = device.id();
259 switch (event.type()) { 324 switch (event.type()) {
260 case DEVICE_ADDED: 325 case DEVICE_ADDED:
326 + pushRules(device);
327 + // FALLTHROUGH
261 case DEVICE_UPDATED: 328 case DEVICE_UPDATED:
262 synchronized (discoverers) { 329 synchronized (discoverers) {
263 ld = discoverers.get(deviceId); 330 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;
......