Kyuhwi Choi
Committed by Gerrit Code Review

[ONOS-4205] support east-west routing in openstackRouting

  - Supports east-west routing traffic
  - Fixes javadocs

Change-Id: I23d9b9497cc2be667fbc9554812c7f5b49c35364
...@@ -20,71 +20,78 @@ import org.onosproject.openstackinterface.OpenstackRouter; ...@@ -20,71 +20,78 @@ import org.onosproject.openstackinterface.OpenstackRouter;
20 import org.onosproject.openstackinterface.OpenstackRouterInterface; 20 import org.onosproject.openstackinterface.OpenstackRouterInterface;
21 21
22 /** 22 /**
23 - * The Interface of Openstack Routing. 23 + * Supports L3 management REST API for openstack.
24 */ 24 */
25 public interface OpenstackRoutingService { 25 public interface OpenstackRoutingService {
26 26
27 /** 27 /**
28 - * Stores the Floating IP information created by Openstack. 28 + * Stores the floating IP information created by openstack.
29 * 29 *
30 - * @param openstackFloatingIP Floating IP information 30 + * @param openstackFloatingIp Floating IP information
31 */ 31 */
32 - void createFloatingIP(OpenstackFloatingIP openstackFloatingIP); 32 + void createFloatingIP(OpenstackFloatingIP openstackFloatingIp);
33 33
34 /** 34 /**
35 - * Updates flow rules corresponding to the Floating IP information updated by Openstack. 35 + * Updates flow rules corresponding to the floating IP information updated by openstack.
36 * 36 *
37 - * @param openstackFloatingIP Floating IP information 37 + * @param openstackFloatingIp Floating IP information
38 */ 38 */
39 - void updateFloatingIP(OpenstackFloatingIP openstackFloatingIP); 39 + void updateFloatingIP(OpenstackFloatingIP openstackFloatingIp);
40 40
41 /** 41 /**
42 - * Removes flow rules corresponding to Floating IP information removed by Openstack. 42 + * Removes flow rules corresponding to floating IP information removed by openstack.
43 * 43 *
44 * @param id Deleted Floating IP`s ID 44 * @param id Deleted Floating IP`s ID
45 */ 45 */
46 void deleteFloatingIP(String id); 46 void deleteFloatingIP(String id);
47 47
48 /** 48 /**
49 - * Stores the router information created by Openstack. 49 + * Stores the router information created by openstack.
50 * 50 *
51 - * @param openstackRouter Floating IP information 51 + * @param openstackRouter Router information
52 */ 52 */
53 void createRouter(OpenstackRouter openstackRouter); 53 void createRouter(OpenstackRouter openstackRouter);
54 54
55 /** 55 /**
56 - * Updates flow rules corresponding to the router information updated by Openstack. 56 + * Updates flow rules corresponding to the router information updated by openstack.
57 * 57 *
58 * @param openstackRouter Router information 58 * @param openstackRouter Router information
59 */ 59 */
60 void updateRouter(OpenstackRouter openstackRouter); 60 void updateRouter(OpenstackRouter openstackRouter);
61 61
62 /** 62 /**
63 - * Removes flow rules corresponding to the router information removed by Openstack. 63 + * Removes flow rules corresponding to the router information removed by openstack.
64 * 64 *
65 * @param id Deleted router`s ID 65 * @param id Deleted router`s ID
66 */ 66 */
67 void deleteRouter(String id); 67 void deleteRouter(String id);
68 68
69 /** 69 /**
70 - * Updates flow rules corresponding to the router information updated by Openstack. 70 + * Updates flow rules corresponding to the router information updated by openstack.
71 * 71 *
72 - * @param openstackRouterInterface Router information 72 + * @param openstackRouterInterface Router interface information
73 */ 73 */
74 void updateRouterInterface(OpenstackRouterInterface openstackRouterInterface); 74 void updateRouterInterface(OpenstackRouterInterface openstackRouterInterface);
75 75
76 /** 76 /**
77 - * Removes flow rules corresponding to the router information removed by Openstack. 77 + * Removes flow rules corresponding to the router information removed by openstack.
78 * 78 *
79 - * @param openstackRouterInterface Router information 79 + * @param openstackRouterInterface Router interface information
80 */ 80 */
81 void removeRouterInterface(OpenstackRouterInterface openstackRouterInterface); 81 void removeRouterInterface(OpenstackRouterInterface openstackRouterInterface);
82 82
83 /** 83 /**
84 - * Checks floatingIp deassociation when corresponding deleted vm. 84 + * Checks floatingIp disassociation when corresponding deleted vm.
85 * 85 *
86 * @param portId Deleted vm 86 * @param portId Deleted vm
87 * @param portInfo stored information about deleted vm 87 * @param portInfo stored information about deleted vm
88 */ 88 */
89 void checkDisassociatedFloatingIp(String portId, OpenstackPortInfo portInfo); 89 void checkDisassociatedFloatingIp(String portId, OpenstackPortInfo portInfo);
90 +
91 + /**
92 + * Returns network id for routerInterface.
93 + *
94 + * @param portId routerInterface`s port id
95 + */
96 + String networkIdForRouterInterface(String portId);
90 } 97 }
......
...@@ -37,6 +37,8 @@ import org.onosproject.net.config.NetworkConfigEvent; ...@@ -37,6 +37,8 @@ import org.onosproject.net.config.NetworkConfigEvent;
37 import org.onosproject.net.config.NetworkConfigListener; 37 import org.onosproject.net.config.NetworkConfigListener;
38 import org.onosproject.net.config.NetworkConfigRegistry; 38 import org.onosproject.net.config.NetworkConfigRegistry;
39 import org.onosproject.net.config.NetworkConfigService; 39 import org.onosproject.net.config.NetworkConfigService;
40 +import org.onosproject.net.device.DeviceEvent;
41 +import org.onosproject.net.device.DeviceListener;
40 import org.onosproject.net.device.DeviceService; 42 import org.onosproject.net.device.DeviceService;
41 import org.onosproject.net.driver.DriverService; 43 import org.onosproject.net.driver.DriverService;
42 import org.onosproject.net.flowobjective.FlowObjectiveService; 44 import org.onosproject.net.flowobjective.FlowObjectiveService;
...@@ -115,12 +117,15 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { ...@@ -115,12 +117,15 @@ public class OpenstackRoutingManager implements OpenstackRoutingService {
115 private ApplicationId appId; 117 private ApplicationId appId;
116 private ConsistentMap<Integer, String> tpPortNumMap; // Map<PortNum, allocated VM`s Mac & destionation Ip address> 118 private ConsistentMap<Integer, String> tpPortNumMap; // Map<PortNum, allocated VM`s Mac & destionation Ip address>
117 private ConsistentMap<String, OpenstackFloatingIP> floatingIpMap; // Map<FloatingIp`s Id, FloatingIp object> 119 private ConsistentMap<String, OpenstackFloatingIP> floatingIpMap; // Map<FloatingIp`s Id, FloatingIp object>
120 + // Map<RouterInterface`s portId, Corresponded port`s network id>
121 + private ConsistentMap<String, String> routerInterfaceMap;
118 private static final String APP_ID = "org.onosproject.openstackrouting"; 122 private static final String APP_ID = "org.onosproject.openstackrouting";
119 private static final String PORT_NAME = "portName"; 123 private static final String PORT_NAME = "portName";
120 private static final String PORTNAME_PREFIX_VM = "tap"; 124 private static final String PORTNAME_PREFIX_VM = "tap";
121 private static final String DEVICE_OWNER_ROUTER_INTERFACE = "network:router_interface"; 125 private static final String DEVICE_OWNER_ROUTER_INTERFACE = "network:router_interface";
122 private static final String FLOATING_IP_MAP_NAME = "openstackrouting-floatingip"; 126 private static final String FLOATING_IP_MAP_NAME = "openstackrouting-floatingip";
123 - private static final String TP_PORT_MAP_NAME = "openstackrouting-portnum"; 127 + private static final String TP_PORT_MAP_NAME = "openstackrouting-tpportnum";
128 + private static final String ROUTER_INTERFACE_MAP_NAME = "openstackrouting-routerinterface";
124 private static final String COLON = ":"; 129 private static final String COLON = ":";
125 private static final int PNAT_PORT_EXPIRE_TIME = 1200 * 1000; 130 private static final int PNAT_PORT_EXPIRE_TIME = 1200 * 1000;
126 private static final int TP_PORT_MINIMUM_NUM = 1024; 131 private static final int TP_PORT_MINIMUM_NUM = 1024;
...@@ -152,7 +157,13 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { ...@@ -152,7 +157,13 @@ public class OpenstackRoutingManager implements OpenstackRoutingService {
152 .register(Integer.class) 157 .register(Integer.class)
153 .register(String.class); 158 .register(String.class);
154 159
160 + private static final KryoNamespace.Builder ROUTER_INTERFACE_SERIALIZER = KryoNamespace.newBuilder()
161 + .register(KryoNamespaces.API)
162 + .register(KryoNamespaces.MISC)
163 + .register(String.class);
164 +
155 private InternalPacketProcessor internalPacketProcessor = new InternalPacketProcessor(); 165 private InternalPacketProcessor internalPacketProcessor = new InternalPacketProcessor();
166 + private InternalDeviceListener internalDeviceListener = new InternalDeviceListener();
156 private ExecutorService l3EventExecutorService = 167 private ExecutorService l3EventExecutorService =
157 Executors.newSingleThreadExecutor(groupedThreads("onos/openstackrouting", "L3-event")); 168 Executors.newSingleThreadExecutor(groupedThreads("onos/openstackrouting", "L3-event"));
158 private ExecutorService icmpEventExecutorService = 169 private ExecutorService icmpEventExecutorService =
...@@ -170,6 +181,7 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { ...@@ -170,6 +181,7 @@ public class OpenstackRoutingManager implements OpenstackRoutingService {
170 packetService.addProcessor(internalPacketProcessor, PacketProcessor.director(1)); 181 packetService.addProcessor(internalPacketProcessor, PacketProcessor.director(1));
171 configRegistry.registerConfigFactory(configFactory); 182 configRegistry.registerConfigFactory(configFactory);
172 configService.addListener(configListener); 183 configService.addListener(configListener);
184 + deviceService.addListener(internalDeviceListener);
173 185
174 floatingIpMap = storageService.<String, OpenstackFloatingIP>consistentMapBuilder() 186 floatingIpMap = storageService.<String, OpenstackFloatingIP>consistentMapBuilder()
175 .withSerializer(Serializer.using(FLOATING_IP_SERIALIZER.build())) 187 .withSerializer(Serializer.using(FLOATING_IP_SERIALIZER.build()))
...@@ -181,52 +193,59 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { ...@@ -181,52 +193,59 @@ public class OpenstackRoutingManager implements OpenstackRoutingService {
181 .withName(TP_PORT_MAP_NAME) 193 .withName(TP_PORT_MAP_NAME)
182 .withApplicationId(appId) 194 .withApplicationId(appId)
183 .build(); 195 .build();
196 + routerInterfaceMap = storageService.<String, String>consistentMapBuilder()
197 + .withSerializer(Serializer.using(ROUTER_INTERFACE_SERIALIZER.build()))
198 + .withName(ROUTER_INTERFACE_MAP_NAME)
199 + .withApplicationId(appId)
200 + .build();
184 201
185 readConfiguration(); 202 readConfiguration();
186 203
187 - log.info("onos-openstackrouting started"); 204 + log.info("started");
188 } 205 }
189 206
190 @Deactivate 207 @Deactivate
191 protected void deactivate() { 208 protected void deactivate() {
192 packetService.removeProcessor(internalPacketProcessor); 209 packetService.removeProcessor(internalPacketProcessor);
210 + deviceService.removeListener(internalDeviceListener);
193 l3EventExecutorService.shutdown(); 211 l3EventExecutorService.shutdown();
194 icmpEventExecutorService.shutdown(); 212 icmpEventExecutorService.shutdown();
195 arpEventExecutorService.shutdown(); 213 arpEventExecutorService.shutdown();
196 214
197 floatingIpMap.clear(); 215 floatingIpMap.clear();
198 tpPortNumMap.clear(); 216 tpPortNumMap.clear();
217 + routerInterfaceMap.clear();
199 218
200 - log.info("onos-openstackrouting stopped"); 219 + log.info("stopped");
201 } 220 }
202 221
203 222
204 @Override 223 @Override
205 - public void createFloatingIP(OpenstackFloatingIP openstackFloatingIP) { 224 + public void createFloatingIP(OpenstackFloatingIP openstackFloatingIp) {
206 - floatingIpMap.put(openstackFloatingIP.id(), openstackFloatingIP); 225 + floatingIpMap.put(openstackFloatingIp.id(), openstackFloatingIp);
207 } 226 }
208 227
209 @Override 228 @Override
210 - public void updateFloatingIP(OpenstackFloatingIP openstackFloatingIP) { 229 + public void updateFloatingIP(OpenstackFloatingIP openstackFloatingIp) {
211 - if (!floatingIpMap.containsKey(openstackFloatingIP.id())) { 230 + if (!floatingIpMap.containsKey(openstackFloatingIp.id())) {
212 - log.warn("There`s no information about {} in FloatingIpMap", openstackFloatingIP.id()); 231 + log.warn("There`s no information about {} in FloatingIpMap", openstackFloatingIp.id());
213 return; 232 return;
214 } 233 }
215 - if (openstackFloatingIP.portId() == null || openstackFloatingIP.portId().equals("null")) { 234 + if (openstackFloatingIp.portId() == null || openstackFloatingIp.portId().equals("null")) {
216 - OpenstackFloatingIP floatingIP = floatingIpMap.get(openstackFloatingIP.id()).value(); 235 + OpenstackFloatingIP floatingIp = floatingIpMap.get(openstackFloatingIp.id()).value();
217 OpenstackPortInfo portInfo = openstackSwitchingService.openstackPortInfo() 236 OpenstackPortInfo portInfo = openstackSwitchingService.openstackPortInfo()
218 - .get(PORTNAME_PREFIX_VM.concat(floatingIP.portId().substring(0, 11))); 237 + .get(PORTNAME_PREFIX_VM.concat(floatingIp.portId().substring(0, 11)));
219 if (portInfo == null) { 238 if (portInfo == null) {
220 - log.warn("There`s no portInfo information about portId {}", floatingIP.portId()); 239 + log.warn("There`s no portInfo information about portId {}", floatingIp.portId());
221 return; 240 return;
222 } 241 }
223 l3EventExecutorService.execute( 242 l3EventExecutorService.execute(
224 - new OpenstackFloatingIPHandler(rulePopulator, floatingIP, false, portInfo)); 243 + new OpenstackFloatingIPHandler(rulePopulator, floatingIp, false, portInfo));
225 - floatingIpMap.replace(floatingIP.id(), openstackFloatingIP); 244 + floatingIpMap.replace(floatingIp.id(), openstackFloatingIp);
226 } else { 245 } else {
227 - floatingIpMap.put(openstackFloatingIP.id(), openstackFloatingIP); 246 + floatingIpMap.put(openstackFloatingIp.id(), openstackFloatingIp);
228 l3EventExecutorService.execute( 247 l3EventExecutorService.execute(
229 - new OpenstackFloatingIPHandler(rulePopulator, openstackFloatingIP, true, null)); 248 + new OpenstackFloatingIPHandler(rulePopulator, openstackFloatingIp, true, null));
230 } 249 }
231 } 250 }
232 251
...@@ -280,11 +299,69 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { ...@@ -280,11 +299,69 @@ public class OpenstackRoutingManager implements OpenstackRoutingService {
280 List<OpenstackRouterInterface> routerInterfaces = Lists.newArrayList(); 299 List<OpenstackRouterInterface> routerInterfaces = Lists.newArrayList();
281 routerInterfaces.add(routerInterface); 300 routerInterfaces.add(routerInterface);
282 checkExternalConnection(getOpenstackRouter(routerInterface.id()), routerInterfaces); 301 checkExternalConnection(getOpenstackRouter(routerInterface.id()), routerInterfaces);
302 + setL3Connection(getOpenstackRouter(routerInterface.id()), null);
303 + routerInterfaceMap.put(routerInterface.portId(), openstackService.port(routerInterface.portId()).networkId());
304 + }
305 +
306 + private void setL3Connection(OpenstackRouter openstackRouter, OpenstackPort openstackPort) {
307 + Collection<OpenstackRouterInterface> interfaceList = getOpenstackRouterInterface(openstackRouter);
308 + if (interfaceList.size() < 2) {
309 + return;
310 + }
311 + if (openstackPort == null) {
312 + interfaceList.forEach(i -> {
313 + OpenstackPort interfacePort = openstackService.port(i.portId());
314 + openstackService.ports()
315 + .stream()
316 + .filter(p -> p.networkId().equals(interfacePort.networkId())
317 + && !p.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE))
318 + .forEach(p -> rulePopulator.populateL3Rules(p,
319 + getL3ConnectionList(p.networkId(), interfaceList)));
320 + });
321 + } else {
322 + rulePopulator.populateL3Rules(openstackPort, getL3ConnectionList(openstackPort.networkId(), interfaceList));
323 + }
324 +
325 + }
326 +
327 + private List<OpenstackRouterInterface> getL3ConnectionList(String networkId,
328 + Collection<OpenstackRouterInterface> interfaceList) {
329 + List<OpenstackRouterInterface> targetList = Lists.newArrayList();
330 + interfaceList.forEach(i -> {
331 + OpenstackPort port = openstackService.port(i.portId());
332 + if (!port.networkId().equals(networkId)) {
333 + targetList.add(i);
334 + }
335 + });
336 + return targetList;
283 } 337 }
284 338
285 @Override 339 @Override
286 public void removeRouterInterface(OpenstackRouterInterface routerInterface) { 340 public void removeRouterInterface(OpenstackRouterInterface routerInterface) {
341 + OpenstackRouter router = openstackService.router(routerInterface.id());
342 + Collection<OpenstackRouterInterface> interfaceList = getOpenstackRouterInterface(router);
343 + if (interfaceList.size() == 1) {
344 + List<OpenstackRouterInterface> newList = Lists.newArrayList();
345 + newList.add(routerInterface);
346 + interfaceList.forEach(i -> removeL3RulesForRouterInterface(i, router, newList));
347 + }
348 + removeL3RulesForRouterInterface(routerInterface, router, null);
287 rulePopulator.removeExternalRules(routerInterface); 349 rulePopulator.removeExternalRules(routerInterface);
350 + routerInterfaceMap.remove(routerInterface.portId());
351 + }
352 +
353 + private void removeL3RulesForRouterInterface(OpenstackRouterInterface routerInterface, OpenstackRouter router,
354 + List<OpenstackRouterInterface> newList) {
355 + openstackService.ports(routerInterfaceMap.get(routerInterface.portId()).value()).forEach(p -> {
356 + Ip4Address vmIp = (Ip4Address) p.fixedIps().values().toArray()[0];
357 + if (newList == null) {
358 + rulePopulator.removeL3Rules(vmIp,
359 + getL3ConnectionList(p.networkId(), getOpenstackRouterInterface(router)));
360 + } else {
361 + rulePopulator.removeL3Rules(vmIp, newList);
362 + }
363 + }
364 + );
288 } 365 }
289 366
290 @Override 367 @Override
...@@ -313,6 +390,11 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { ...@@ -313,6 +390,11 @@ public class OpenstackRoutingManager implements OpenstackRoutingService {
313 } 390 }
314 } 391 }
315 392
393 + @Override
394 + public String networkIdForRouterInterface(String portId) {
395 + return routerInterfaceMap.get(portId).value();
396 + }
397 +
316 private Collection<OpenstackFloatingIP> associatedFloatingIps() { 398 private Collection<OpenstackFloatingIP> associatedFloatingIps() {
317 List<OpenstackFloatingIP> fIps = Lists.newArrayList(); 399 List<OpenstackFloatingIP> fIps = Lists.newArrayList();
318 floatingIpMap.values() 400 floatingIpMap.values()
...@@ -327,10 +409,7 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { ...@@ -327,10 +409,7 @@ public class OpenstackRoutingManager implements OpenstackRoutingService {
327 openstackService.ports() 409 openstackService.ports()
328 .stream() 410 .stream()
329 .filter(p -> p.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE)) 411 .filter(p -> p.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE))
330 - .forEach(p -> { 412 + .forEach(p -> updateRouterInterface(portToRouterInterface(p)))
331 - OpenstackRouterInterface routerInterface = portToRouterInterface(p);
332 - updateRouterInterface(routerInterface);
333 - })
334 ); 413 );
335 414
336 } 415 }
...@@ -382,14 +461,13 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { ...@@ -382,14 +461,13 @@ public class OpenstackRoutingManager implements OpenstackRoutingService {
382 int portNum = getPortNum(ethernet.getSourceMAC(), iPacket.getDestinationAddress()); 461 int portNum = getPortNum(ethernet.getSourceMAC(), iPacket.getDestinationAddress());
383 Optional<Port> port = 462 Optional<Port> port =
384 getExternalPort(pkt.receivedFrom().deviceId(), config.gatewayExternalInterfaceName()); 463 getExternalPort(pkt.receivedFrom().deviceId(), config.gatewayExternalInterfaceName());
385 - 464 + if (port.isPresent()) {
386 - if (!port.isPresent()) {
387 - log.warn("There`s no external interface");
388 - } else {
389 OpenstackPort openstackPort = getOpenstackPort(ethernet.getSourceMAC(), 465 OpenstackPort openstackPort = getOpenstackPort(ethernet.getSourceMAC(),
390 Ip4Address.valueOf(iPacket.getSourceAddress())); 466 Ip4Address.valueOf(iPacket.getSourceAddress()));
391 l3EventExecutorService.execute(new OpenstackPnatHandler(rulePopulator, context, 467 l3EventExecutorService.execute(new OpenstackPnatHandler(rulePopulator, context,
392 portNum, openstackPort, port.get(), config)); 468 portNum, openstackPort, port.get(), config));
469 + } else {
470 + log.warn("There`s no external interface");
393 } 471 }
394 break; 472 break;
395 } 473 }
...@@ -471,22 +549,20 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { ...@@ -471,22 +549,20 @@ public class OpenstackRoutingManager implements OpenstackRoutingService {
471 List<OpenstackRouterInterface> interfaces = Lists.newArrayList(); 549 List<OpenstackRouterInterface> interfaces = Lists.newArrayList();
472 openstackService.ports() 550 openstackService.ports()
473 .stream() 551 .stream()
474 - .filter(p -> p.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE)) 552 + .filter(p -> p.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE)
475 - .filter(p -> p.deviceId().equals(router.id())) 553 + && p.deviceId().equals(router.id()))
476 - .forEach(p -> { 554 + .forEach(p -> interfaces.add(portToRouterInterface(p)));
477 - interfaces.add(portToRouterInterface(p));
478 - });
479 return interfaces; 555 return interfaces;
480 } 556 }
481 557
482 private OpenstackRouter getOpenstackRouter(String id) { 558 private OpenstackRouter getOpenstackRouter(String id) {
483 return openstackService.routers().stream().filter(r -> 559 return openstackService.routers().stream().filter(r ->
484 - r.id().equals(id)).findAny().orElse(null); 560 + r.id().equals(id)).iterator().next();
485 } 561 }
486 562
487 private OpenstackPort getOpenstackPort(MacAddress sourceMac, Ip4Address ip4Address) { 563 private OpenstackPort getOpenstackPort(MacAddress sourceMac, Ip4Address ip4Address) {
488 OpenstackPort openstackPort = openstackService.ports().stream() 564 OpenstackPort openstackPort = openstackService.ports().stream()
489 - .filter(p -> p.macAddress().equals(sourceMac)).findFirst().orElse(null); 565 + .filter(p -> p.macAddress().equals(sourceMac)).iterator().next();
490 return openstackPort.fixedIps().values().stream().filter(ip -> 566 return openstackPort.fixedIps().values().stream().filter(ip ->
491 ip.equals(ip4Address)).count() > 0 ? openstackPort : null; 567 ip.equals(ip4Address)).count() > 0 ? openstackPort : null;
492 } 568 }
...@@ -534,4 +610,38 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { ...@@ -534,4 +610,38 @@ public class OpenstackRoutingManager implements OpenstackRoutingService {
534 } 610 }
535 } 611 }
536 } 612 }
613 +
614 + private class InternalDeviceListener implements DeviceListener {
615 +
616 + @Override
617 + public void event(DeviceEvent deviceEvent) {
618 + if (deviceEvent.type() == DeviceEvent.Type.PORT_UPDATED) {
619 + Port port = deviceEvent.port();
620 + OpenstackPortInfo portInfo = openstackSwitchingService.openstackPortInfo()
621 + .get(port.annotations().value(PORT_NAME));
622 + OpenstackPort openstackPort = openstackService.port(port);
623 + OpenstackPort interfacePort = openstackService.ports()
624 + .stream()
625 + .filter(p -> p.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE)
626 + && p.networkId().equals(openstackPort.networkId()))
627 + .findAny()
628 + .orElse(null);
629 + if (portInfo == null && openstackPort == null) {
630 + log.warn("As delete event timing issue between routing and switching, Can`t delete L3 rules");
631 + return;
632 + }
633 + if ((port.isEnabled()) && (interfacePort != null)) {
634 + OpenstackRouterInterface routerInterface = portToRouterInterface(interfacePort);
635 + l3EventExecutorService.execute(() ->
636 + setL3Connection(getOpenstackRouter(routerInterface.id()), openstackPort));
637 + } else if (interfacePort != null) {
638 + OpenstackRouterInterface routerInterface = portToRouterInterface(interfacePort);
639 + l3EventExecutorService.execute(() -> rulePopulator.removeL3Rules(portInfo.ip(),
640 + getL3ConnectionList(portInfo.networkId(),
641 + getOpenstackRouterInterface(getOpenstackRouter(routerInterface.id())))));
642 + }
643 + }
644 + }
645 + }
646 +
537 } 647 }
......
...@@ -54,12 +54,15 @@ import org.onosproject.openstackinterface.OpenstackSubnet; ...@@ -54,12 +54,15 @@ import org.onosproject.openstackinterface.OpenstackSubnet;
54 import org.onosproject.openstackinterface.OpenstackFloatingIP; 54 import org.onosproject.openstackinterface.OpenstackFloatingIP;
55 import org.onosproject.openstacknetworking.OpenstackNetworkingConfig; 55 import org.onosproject.openstacknetworking.OpenstackNetworkingConfig;
56 import org.onosproject.openstacknetworking.OpenstackPortInfo; 56 import org.onosproject.openstacknetworking.OpenstackPortInfo;
57 +import org.onosproject.openstacknetworking.OpenstackRoutingService;
57 import org.slf4j.Logger; 58 import org.slf4j.Logger;
58 import org.slf4j.LoggerFactory; 59 import org.slf4j.LoggerFactory;
59 60
61 +import java.util.List;
60 import java.util.stream.StreamSupport; 62 import java.util.stream.StreamSupport;
61 63
62 import static com.google.common.base.Preconditions.checkNotNull; 64 import static com.google.common.base.Preconditions.checkNotNull;
65 +import static org.onlab.osgi.DefaultServiceDirectory.getService;
63 66
64 /** 67 /**
65 * Populates Routing Flow Rules. 68 * Populates Routing Flow Rules.
...@@ -99,11 +102,11 @@ public class OpenstackRoutingRulePopulator { ...@@ -99,11 +102,11 @@ public class OpenstackRoutingRulePopulator {
99 * The constructor of openstackRoutingRulePopulator. 102 * The constructor of openstackRoutingRulePopulator.
100 * 103 *
101 * @param appId Caller`s appId 104 * @param appId Caller`s appId
102 - * @param openstackService OpenstackNetworkingService 105 + * @param openstackService Opestack REST request handler
103 * @param flowObjectiveService FlowObjectiveService 106 * @param flowObjectiveService FlowObjectiveService
104 * @param deviceService DeviceService 107 * @param deviceService DeviceService
105 * @param driverService DriverService 108 * @param driverService DriverService
106 - * @param config OpenstackRoutingConfig 109 + * @param config Configuration for openstack environment
107 */ 110 */
108 public OpenstackRoutingRulePopulator(ApplicationId appId, OpenstackInterfaceService openstackService, 111 public OpenstackRoutingRulePopulator(ApplicationId appId, OpenstackInterfaceService openstackService,
109 FlowObjectiveService flowObjectiveService, DeviceService deviceService, 112 FlowObjectiveService flowObjectiveService, DeviceService deviceService,
...@@ -187,6 +190,7 @@ public class OpenstackRoutingRulePopulator { ...@@ -187,6 +190,7 @@ public class OpenstackRoutingRulePopulator {
187 .add(); 190 .add();
188 191
189 flowObjectiveService.forward(inboundPacket.receivedFrom().deviceId(), fo); 192 flowObjectiveService.forward(inboundPacket.receivedFrom().deviceId(), fo);
193 +
190 } 194 }
191 195
192 private Port getPortOfExternalInterface() { 196 private Port getPortOfExternalInterface() {
...@@ -252,8 +256,8 @@ public class OpenstackRoutingRulePopulator { ...@@ -252,8 +256,8 @@ public class OpenstackRoutingRulePopulator {
252 String openstackPortName = PORTNAME_PREFIX_VM + openstackPort.id().substring(0, 11); 256 String openstackPortName = PORTNAME_PREFIX_VM + openstackPort.id().substring(0, 11);
253 Device device = StreamSupport.stream(deviceService.getDevices().spliterator(), false) 257 Device device = StreamSupport.stream(deviceService.getDevices().spliterator(), false)
254 .filter(d -> findPortinDevice(d, openstackPortName)) 258 .filter(d -> findPortinDevice(d, openstackPortName))
255 - .findAny() 259 + .iterator()
256 - .orElse(null); 260 + .next();
257 checkNotNull(device, DEVICENOTNULL); 261 checkNotNull(device, DEVICENOTNULL);
258 return device; 262 return device;
259 } 263 }
...@@ -268,7 +272,7 @@ public class OpenstackRoutingRulePopulator { ...@@ -268,7 +272,7 @@ public class OpenstackRoutingRulePopulator {
268 } 272 }
269 273
270 /** 274 /**
271 - * Builds NiciraExtension for tagging remoteIp of vxlan. 275 + * Builds Nicira extension for tagging remoteIp of vxlan.
272 * 276 *
273 * @param id Device Id of vxlan source device 277 * @param id Device Id of vxlan source device
274 * @param hostIp Remote Ip of vxlan destination device 278 * @param hostIp Remote Ip of vxlan destination device
...@@ -401,8 +405,8 @@ public class OpenstackRoutingRulePopulator { ...@@ -401,8 +405,8 @@ public class OpenstackRoutingRulePopulator {
401 StreamSupport.stream(deviceService.getDevices().spliterator(), false) 405 StreamSupport.stream(deviceService.getDevices().spliterator(), false)
402 .forEach(d -> { 406 .forEach(d -> {
403 ForwardingObjective.Flag flag = checkGatewayNode(d.id()) ? 407 ForwardingObjective.Flag flag = checkGatewayNode(d.id()) ?
404 - ForwardingObjective.Flag.VERSATILE : ForwardingObjective.Flag.SPECIFIC; 408 + ForwardingObjective.Flag.VERSATILE :
405 - 409 + ForwardingObjective.Flag.SPECIFIC;
406 removeRule(d.id(), sBuilder, flag, ROUTING_RULE_PRIORITY); 410 removeRule(d.id(), sBuilder, flag, ROUTING_RULE_PRIORITY);
407 }); 411 });
408 412
...@@ -514,4 +518,120 @@ public class OpenstackRoutingRulePopulator { ...@@ -514,4 +518,120 @@ public class OpenstackRoutingRulePopulator {
514 removeRule(getGatewayNode().id(), sIncomingBuilder, ForwardingObjective.Flag.VERSATILE, FLOATING_RULE_PRIORITY); 518 removeRule(getGatewayNode().id(), sIncomingBuilder, ForwardingObjective.Flag.VERSATILE, FLOATING_RULE_PRIORITY);
515 } 519 }
516 520
521 + /**
522 + * Populates L3 rules for east to west traffic.
523 + *
524 + * @param p target VM
525 + * @param targetList target openstackRouterInterfaces
526 + */
527 + public void populateL3Rules(OpenstackPort p, List<OpenstackRouterInterface> targetList) {
528 + Device device = getDevicefromOpenstackPort(p);
529 + Port port = getPortFromOpenstackPort(device, p);
530 + Ip4Address vmIp = (Ip4Address) p.fixedIps().values().iterator().next();
531 +
532 + if (port == null) {
533 + return;
534 + }
535 +
536 + targetList.forEach(routerInterface -> {
537 + OpenstackPort openstackPort = openstackService.port(routerInterface.portId());
538 + long vni = getVni(openstackPort.networkId());
539 +
540 + if (vmIp == null) {
541 + return;
542 + }
543 +
544 + populateL3RulestoSameNode(vmIp, p, port, device, vni);
545 +
546 + deviceService.getAvailableDevices().forEach(d -> {
547 + if (!d.equals(device) && !d.equals(getGatewayNode())) {
548 + populateL3RulestoDifferentNode(vmIp, vni, d.id(), getHostIpfromOpenstackPort(p));
549 + }
550 + });
551 +
552 + });
553 + }
554 +
555 + private void populateL3RulestoDifferentNode(Ip4Address vmIp, long vni, DeviceId deviceId, Ip4Address hostIp) {
556 + TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
557 + TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
558 +
559 + sBuilder.matchEthType(Ethernet.TYPE_IPV4)
560 + .matchTunnelId(vni)
561 + .matchIPDst(vmIp.toIpPrefix());
562 + tBuilder.extension(buildNiciraExtenstion(deviceId, hostIp), deviceId)
563 + .setOutput(getTunnelPort(deviceId));
564 +
565 + ForwardingObjective fo = DefaultForwardingObjective.builder()
566 + .withSelector(sBuilder.build())
567 + .withTreatment(tBuilder.build())
568 + .withPriority(ROUTING_RULE_PRIORITY)
569 + .withFlag(ForwardingObjective.Flag.SPECIFIC)
570 + .fromApp(appId)
571 + .add();
572 +
573 + flowObjectiveService.forward(deviceId, fo);
574 + }
575 +
576 + private void populateL3RulestoSameNode(Ip4Address vmIp, OpenstackPort p, Port port, Device device, long vni) {
577 + TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
578 + TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
579 +
580 + sBuilder.matchEthType(Ethernet.TYPE_IPV4)
581 + .matchIPDst(vmIp.toIpPrefix())
582 + .matchTunnelId(vni);
583 +
584 + tBuilder.setEthDst(p.macAddress())
585 + .setOutput(port.number());
586 +
587 + ForwardingObjective fo = DefaultForwardingObjective.builder()
588 + .withSelector(sBuilder.build())
589 + .withTreatment(tBuilder.build())
590 + .withPriority(ROUTING_RULE_PRIORITY)
591 + .withFlag(ForwardingObjective.Flag.SPECIFIC)
592 + .fromApp(appId)
593 + .add();
594 +
595 + flowObjectiveService.forward(device.id(), fo);
596 + }
597 +
598 + private Port getPortFromOpenstackPort(Device device, OpenstackPort p) {
599 + String openstackPortName = PORTNAME_PREFIX_VM + p.id().substring(0, 11);
600 + return deviceService.getPorts(device.id())
601 + .stream()
602 + .filter(pt -> pt.annotations().value(PORTNAME).equals(openstackPortName))
603 + .findAny()
604 + .orElse(null);
605 + }
606 +
607 + /**
608 + * Removes L3 rules for routerInterface events.
609 + *
610 + * @param vmIp Corresponding Vm ip
611 + * @param routerInterfaces Corresponding routerInterfaces
612 + */
613 + public void removeL3Rules(Ip4Address vmIp, List<OpenstackRouterInterface> routerInterfaces) {
614 + if (vmIp == null) {
615 + return;
616 + }
617 +
618 + OpenstackRoutingService routingService = getService(OpenstackRoutingService.class);
619 +
620 + deviceService.getAvailableDevices().forEach(d -> {
621 + if (!d.equals(getGatewayNode())) {
622 + routerInterfaces.forEach(routerInterface -> {
623 + String networkId = routingService.networkIdForRouterInterface(routerInterface.portId());
624 + long vni = getVni(networkId);
625 +
626 + TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
627 +
628 + sBuilder.matchEthType(Ethernet.TYPE_IPV4)
629 + .matchIPDst(vmIp.toIpPrefix())
630 + .matchTunnelId(vni);
631 +
632 + removeRule(d.id(), sBuilder, ForwardingObjective.Flag.SPECIFIC, ROUTING_RULE_PRIORITY);
633 + });
634 + }
635 + });
636 + }
517 } 637 }
......