diff --git a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/OpenstackRoutingService.java b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/OpenstackRoutingService.java index 304325dc70..7fe75b435b 100644 --- a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/OpenstackRoutingService.java +++ b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/OpenstackRoutingService.java @@ -20,71 +20,78 @@ import org.onosproject.openstackinterface.OpenstackRouter; import org.onosproject.openstackinterface.OpenstackRouterInterface; /** - * The Interface of Openstack Routing. + * Supports L3 management REST API for openstack. */ public interface OpenstackRoutingService { /** - * Stores the Floating IP information created by Openstack. + * Stores the floating IP information created by openstack. * - * @param openstackFloatingIP Floating IP information + * @param openstackFloatingIp Floating IP information */ - void createFloatingIP(OpenstackFloatingIP openstackFloatingIP); + void createFloatingIP(OpenstackFloatingIP openstackFloatingIp); /** - * Updates flow rules corresponding to the Floating IP information updated by Openstack. + * Updates flow rules corresponding to the floating IP information updated by openstack. * - * @param openstackFloatingIP Floating IP information + * @param openstackFloatingIp Floating IP information */ - void updateFloatingIP(OpenstackFloatingIP openstackFloatingIP); + void updateFloatingIP(OpenstackFloatingIP openstackFloatingIp); /** - * Removes flow rules corresponding to Floating IP information removed by Openstack. + * Removes flow rules corresponding to floating IP information removed by openstack. * * @param id Deleted Floating IP`s ID */ void deleteFloatingIP(String id); /** - * Stores the router information created by Openstack. + * Stores the router information created by openstack. * - * @param openstackRouter Floating IP information + * @param openstackRouter Router information */ void createRouter(OpenstackRouter openstackRouter); /** - * Updates flow rules corresponding to the router information updated by Openstack. + * Updates flow rules corresponding to the router information updated by openstack. * * @param openstackRouter Router information */ void updateRouter(OpenstackRouter openstackRouter); /** - * Removes flow rules corresponding to the router information removed by Openstack. + * Removes flow rules corresponding to the router information removed by openstack. * * @param id Deleted router`s ID */ void deleteRouter(String id); /** - * Updates flow rules corresponding to the router information updated by Openstack. + * Updates flow rules corresponding to the router information updated by openstack. * - * @param openstackRouterInterface Router information + * @param openstackRouterInterface Router interface information */ void updateRouterInterface(OpenstackRouterInterface openstackRouterInterface); /** - * Removes flow rules corresponding to the router information removed by Openstack. + * Removes flow rules corresponding to the router information removed by openstack. * - * @param openstackRouterInterface Router information + * @param openstackRouterInterface Router interface information */ void removeRouterInterface(OpenstackRouterInterface openstackRouterInterface); /** - * Checks floatingIp deassociation when corresponding deleted vm. + * Checks floatingIp disassociation when corresponding deleted vm. * * @param portId Deleted vm * @param portInfo stored information about deleted vm */ void checkDisassociatedFloatingIp(String portId, OpenstackPortInfo portInfo); + + /** + * Returns network id for routerInterface. + * + * @param portId routerInterface`s port id + */ + String networkIdForRouterInterface(String portId); } diff --git a/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingManager.java b/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingManager.java index 62e8cdf3d0..781dfa75dd 100644 --- a/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingManager.java +++ b/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingManager.java @@ -37,6 +37,8 @@ import org.onosproject.net.config.NetworkConfigEvent; import org.onosproject.net.config.NetworkConfigListener; import org.onosproject.net.config.NetworkConfigRegistry; import org.onosproject.net.config.NetworkConfigService; +import org.onosproject.net.device.DeviceEvent; +import org.onosproject.net.device.DeviceListener; import org.onosproject.net.device.DeviceService; import org.onosproject.net.driver.DriverService; import org.onosproject.net.flowobjective.FlowObjectiveService; @@ -115,12 +117,15 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { private ApplicationId appId; private ConsistentMap tpPortNumMap; // Map private ConsistentMap floatingIpMap; // Map + // Map + private ConsistentMap routerInterfaceMap; private static final String APP_ID = "org.onosproject.openstackrouting"; private static final String PORT_NAME = "portName"; private static final String PORTNAME_PREFIX_VM = "tap"; private static final String DEVICE_OWNER_ROUTER_INTERFACE = "network:router_interface"; private static final String FLOATING_IP_MAP_NAME = "openstackrouting-floatingip"; - private static final String TP_PORT_MAP_NAME = "openstackrouting-portnum"; + private static final String TP_PORT_MAP_NAME = "openstackrouting-tpportnum"; + private static final String ROUTER_INTERFACE_MAP_NAME = "openstackrouting-routerinterface"; private static final String COLON = ":"; private static final int PNAT_PORT_EXPIRE_TIME = 1200 * 1000; private static final int TP_PORT_MINIMUM_NUM = 1024; @@ -152,7 +157,13 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { .register(Integer.class) .register(String.class); + private static final KryoNamespace.Builder ROUTER_INTERFACE_SERIALIZER = KryoNamespace.newBuilder() + .register(KryoNamespaces.API) + .register(KryoNamespaces.MISC) + .register(String.class); + private InternalPacketProcessor internalPacketProcessor = new InternalPacketProcessor(); + private InternalDeviceListener internalDeviceListener = new InternalDeviceListener(); private ExecutorService l3EventExecutorService = Executors.newSingleThreadExecutor(groupedThreads("onos/openstackrouting", "L3-event")); private ExecutorService icmpEventExecutorService = @@ -170,6 +181,7 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { packetService.addProcessor(internalPacketProcessor, PacketProcessor.director(1)); configRegistry.registerConfigFactory(configFactory); configService.addListener(configListener); + deviceService.addListener(internalDeviceListener); floatingIpMap = storageService.consistentMapBuilder() .withSerializer(Serializer.using(FLOATING_IP_SERIALIZER.build())) @@ -181,52 +193,59 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { .withName(TP_PORT_MAP_NAME) .withApplicationId(appId) .build(); + routerInterfaceMap = storageService.consistentMapBuilder() + .withSerializer(Serializer.using(ROUTER_INTERFACE_SERIALIZER.build())) + .withName(ROUTER_INTERFACE_MAP_NAME) + .withApplicationId(appId) + .build(); readConfiguration(); - log.info("onos-openstackrouting started"); + log.info("started"); } @Deactivate protected void deactivate() { packetService.removeProcessor(internalPacketProcessor); + deviceService.removeListener(internalDeviceListener); l3EventExecutorService.shutdown(); icmpEventExecutorService.shutdown(); arpEventExecutorService.shutdown(); floatingIpMap.clear(); tpPortNumMap.clear(); + routerInterfaceMap.clear(); - log.info("onos-openstackrouting stopped"); + log.info("stopped"); } @Override - public void createFloatingIP(OpenstackFloatingIP openstackFloatingIP) { - floatingIpMap.put(openstackFloatingIP.id(), openstackFloatingIP); + public void createFloatingIP(OpenstackFloatingIP openstackFloatingIp) { + floatingIpMap.put(openstackFloatingIp.id(), openstackFloatingIp); } @Override - public void updateFloatingIP(OpenstackFloatingIP openstackFloatingIP) { - if (!floatingIpMap.containsKey(openstackFloatingIP.id())) { - log.warn("There`s no information about {} in FloatingIpMap", openstackFloatingIP.id()); + public void updateFloatingIP(OpenstackFloatingIP openstackFloatingIp) { + if (!floatingIpMap.containsKey(openstackFloatingIp.id())) { + log.warn("There`s no information about {} in FloatingIpMap", openstackFloatingIp.id()); return; } - if (openstackFloatingIP.portId() == null || openstackFloatingIP.portId().equals("null")) { - OpenstackFloatingIP floatingIP = floatingIpMap.get(openstackFloatingIP.id()).value(); + if (openstackFloatingIp.portId() == null || openstackFloatingIp.portId().equals("null")) { + OpenstackFloatingIP floatingIp = floatingIpMap.get(openstackFloatingIp.id()).value(); OpenstackPortInfo portInfo = openstackSwitchingService.openstackPortInfo() - .get(PORTNAME_PREFIX_VM.concat(floatingIP.portId().substring(0, 11))); + .get(PORTNAME_PREFIX_VM.concat(floatingIp.portId().substring(0, 11))); if (portInfo == null) { - log.warn("There`s no portInfo information about portId {}", floatingIP.portId()); + log.warn("There`s no portInfo information about portId {}", floatingIp.portId()); return; } l3EventExecutorService.execute( - new OpenstackFloatingIPHandler(rulePopulator, floatingIP, false, portInfo)); - floatingIpMap.replace(floatingIP.id(), openstackFloatingIP); + new OpenstackFloatingIPHandler(rulePopulator, floatingIp, false, portInfo)); + floatingIpMap.replace(floatingIp.id(), openstackFloatingIp); } else { - floatingIpMap.put(openstackFloatingIP.id(), openstackFloatingIP); + floatingIpMap.put(openstackFloatingIp.id(), openstackFloatingIp); l3EventExecutorService.execute( - new OpenstackFloatingIPHandler(rulePopulator, openstackFloatingIP, true, null)); + new OpenstackFloatingIPHandler(rulePopulator, openstackFloatingIp, true, null)); } } @@ -280,11 +299,69 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { List routerInterfaces = Lists.newArrayList(); routerInterfaces.add(routerInterface); checkExternalConnection(getOpenstackRouter(routerInterface.id()), routerInterfaces); + setL3Connection(getOpenstackRouter(routerInterface.id()), null); + routerInterfaceMap.put(routerInterface.portId(), openstackService.port(routerInterface.portId()).networkId()); + } + + private void setL3Connection(OpenstackRouter openstackRouter, OpenstackPort openstackPort) { + Collection interfaceList = getOpenstackRouterInterface(openstackRouter); + if (interfaceList.size() < 2) { + return; + } + if (openstackPort == null) { + interfaceList.forEach(i -> { + OpenstackPort interfacePort = openstackService.port(i.portId()); + openstackService.ports() + .stream() + .filter(p -> p.networkId().equals(interfacePort.networkId()) + && !p.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE)) + .forEach(p -> rulePopulator.populateL3Rules(p, + getL3ConnectionList(p.networkId(), interfaceList))); + }); + } else { + rulePopulator.populateL3Rules(openstackPort, getL3ConnectionList(openstackPort.networkId(), interfaceList)); + } + + } + + private List getL3ConnectionList(String networkId, + Collection interfaceList) { + List targetList = Lists.newArrayList(); + interfaceList.forEach(i -> { + OpenstackPort port = openstackService.port(i.portId()); + if (!port.networkId().equals(networkId)) { + targetList.add(i); + } + }); + return targetList; } @Override public void removeRouterInterface(OpenstackRouterInterface routerInterface) { + OpenstackRouter router = openstackService.router(routerInterface.id()); + Collection interfaceList = getOpenstackRouterInterface(router); + if (interfaceList.size() == 1) { + List newList = Lists.newArrayList(); + newList.add(routerInterface); + interfaceList.forEach(i -> removeL3RulesForRouterInterface(i, router, newList)); + } + removeL3RulesForRouterInterface(routerInterface, router, null); rulePopulator.removeExternalRules(routerInterface); + routerInterfaceMap.remove(routerInterface.portId()); + } + + private void removeL3RulesForRouterInterface(OpenstackRouterInterface routerInterface, OpenstackRouter router, + List newList) { + openstackService.ports(routerInterfaceMap.get(routerInterface.portId()).value()).forEach(p -> { + Ip4Address vmIp = (Ip4Address) p.fixedIps().values().toArray()[0]; + if (newList == null) { + rulePopulator.removeL3Rules(vmIp, + getL3ConnectionList(p.networkId(), getOpenstackRouterInterface(router))); + } else { + rulePopulator.removeL3Rules(vmIp, newList); + } + } + ); } @Override @@ -313,6 +390,11 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { } } + @Override + public String networkIdForRouterInterface(String portId) { + return routerInterfaceMap.get(portId).value(); + } + private Collection associatedFloatingIps() { List fIps = Lists.newArrayList(); floatingIpMap.values() @@ -327,10 +409,7 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { openstackService.ports() .stream() .filter(p -> p.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE)) - .forEach(p -> { - OpenstackRouterInterface routerInterface = portToRouterInterface(p); - updateRouterInterface(routerInterface); - }) + .forEach(p -> updateRouterInterface(portToRouterInterface(p))) ); } @@ -382,14 +461,13 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { int portNum = getPortNum(ethernet.getSourceMAC(), iPacket.getDestinationAddress()); Optional port = getExternalPort(pkt.receivedFrom().deviceId(), config.gatewayExternalInterfaceName()); - - if (!port.isPresent()) { - log.warn("There`s no external interface"); - } else { + if (port.isPresent()) { OpenstackPort openstackPort = getOpenstackPort(ethernet.getSourceMAC(), Ip4Address.valueOf(iPacket.getSourceAddress())); l3EventExecutorService.execute(new OpenstackPnatHandler(rulePopulator, context, portNum, openstackPort, port.get(), config)); + } else { + log.warn("There`s no external interface"); } break; } @@ -471,22 +549,20 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { List interfaces = Lists.newArrayList(); openstackService.ports() .stream() - .filter(p -> p.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE)) - .filter(p -> p.deviceId().equals(router.id())) - .forEach(p -> { - interfaces.add(portToRouterInterface(p)); - }); + .filter(p -> p.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE) + && p.deviceId().equals(router.id())) + .forEach(p -> interfaces.add(portToRouterInterface(p))); return interfaces; } private OpenstackRouter getOpenstackRouter(String id) { return openstackService.routers().stream().filter(r -> - r.id().equals(id)).findAny().orElse(null); + r.id().equals(id)).iterator().next(); } private OpenstackPort getOpenstackPort(MacAddress sourceMac, Ip4Address ip4Address) { OpenstackPort openstackPort = openstackService.ports().stream() - .filter(p -> p.macAddress().equals(sourceMac)).findFirst().orElse(null); + .filter(p -> p.macAddress().equals(sourceMac)).iterator().next(); return openstackPort.fixedIps().values().stream().filter(ip -> ip.equals(ip4Address)).count() > 0 ? openstackPort : null; } @@ -534,4 +610,38 @@ public class OpenstackRoutingManager implements OpenstackRoutingService { } } } + + private class InternalDeviceListener implements DeviceListener { + + @Override + public void event(DeviceEvent deviceEvent) { + if (deviceEvent.type() == DeviceEvent.Type.PORT_UPDATED) { + Port port = deviceEvent.port(); + OpenstackPortInfo portInfo = openstackSwitchingService.openstackPortInfo() + .get(port.annotations().value(PORT_NAME)); + OpenstackPort openstackPort = openstackService.port(port); + OpenstackPort interfacePort = openstackService.ports() + .stream() + .filter(p -> p.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE) + && p.networkId().equals(openstackPort.networkId())) + .findAny() + .orElse(null); + if (portInfo == null && openstackPort == null) { + log.warn("As delete event timing issue between routing and switching, Can`t delete L3 rules"); + return; + } + if ((port.isEnabled()) && (interfacePort != null)) { + OpenstackRouterInterface routerInterface = portToRouterInterface(interfacePort); + l3EventExecutorService.execute(() -> + setL3Connection(getOpenstackRouter(routerInterface.id()), openstackPort)); + } else if (interfacePort != null) { + OpenstackRouterInterface routerInterface = portToRouterInterface(interfacePort); + l3EventExecutorService.execute(() -> rulePopulator.removeL3Rules(portInfo.ip(), + getL3ConnectionList(portInfo.networkId(), + getOpenstackRouterInterface(getOpenstackRouter(routerInterface.id()))))); + } + } + } + } + } diff --git a/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingRulePopulator.java b/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingRulePopulator.java index 5616e0ace1..2207ff6324 100644 --- a/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingRulePopulator.java +++ b/apps/openstacknetworking/openstackrouting/src/main/java/org/onosproject/openstacknetworking/routing/OpenstackRoutingRulePopulator.java @@ -54,12 +54,15 @@ import org.onosproject.openstackinterface.OpenstackSubnet; import org.onosproject.openstackinterface.OpenstackFloatingIP; import org.onosproject.openstacknetworking.OpenstackNetworkingConfig; import org.onosproject.openstacknetworking.OpenstackPortInfo; +import org.onosproject.openstacknetworking.OpenstackRoutingService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.List; import java.util.stream.StreamSupport; import static com.google.common.base.Preconditions.checkNotNull; +import static org.onlab.osgi.DefaultServiceDirectory.getService; /** * Populates Routing Flow Rules. @@ -99,11 +102,11 @@ public class OpenstackRoutingRulePopulator { * The constructor of openstackRoutingRulePopulator. * * @param appId Caller`s appId - * @param openstackService OpenstackNetworkingService + * @param openstackService Opestack REST request handler * @param flowObjectiveService FlowObjectiveService * @param deviceService DeviceService * @param driverService DriverService - * @param config OpenstackRoutingConfig + * @param config Configuration for openstack environment */ public OpenstackRoutingRulePopulator(ApplicationId appId, OpenstackInterfaceService openstackService, FlowObjectiveService flowObjectiveService, DeviceService deviceService, @@ -187,6 +190,7 @@ public class OpenstackRoutingRulePopulator { .add(); flowObjectiveService.forward(inboundPacket.receivedFrom().deviceId(), fo); + } private Port getPortOfExternalInterface() { @@ -252,8 +256,8 @@ public class OpenstackRoutingRulePopulator { String openstackPortName = PORTNAME_PREFIX_VM + openstackPort.id().substring(0, 11); Device device = StreamSupport.stream(deviceService.getDevices().spliterator(), false) .filter(d -> findPortinDevice(d, openstackPortName)) - .findAny() - .orElse(null); + .iterator() + .next(); checkNotNull(device, DEVICENOTNULL); return device; } @@ -268,7 +272,7 @@ public class OpenstackRoutingRulePopulator { } /** - * Builds NiciraExtension for tagging remoteIp of vxlan. + * Builds Nicira extension for tagging remoteIp of vxlan. * * @param id Device Id of vxlan source device * @param hostIp Remote Ip of vxlan destination device @@ -401,8 +405,8 @@ public class OpenstackRoutingRulePopulator { StreamSupport.stream(deviceService.getDevices().spliterator(), false) .forEach(d -> { ForwardingObjective.Flag flag = checkGatewayNode(d.id()) ? - ForwardingObjective.Flag.VERSATILE : ForwardingObjective.Flag.SPECIFIC; - + ForwardingObjective.Flag.VERSATILE : + ForwardingObjective.Flag.SPECIFIC; removeRule(d.id(), sBuilder, flag, ROUTING_RULE_PRIORITY); }); @@ -514,4 +518,120 @@ public class OpenstackRoutingRulePopulator { removeRule(getGatewayNode().id(), sIncomingBuilder, ForwardingObjective.Flag.VERSATILE, FLOATING_RULE_PRIORITY); } + /** + * Populates L3 rules for east to west traffic. + * + * @param p target VM + * @param targetList target openstackRouterInterfaces + */ + public void populateL3Rules(OpenstackPort p, List targetList) { + Device device = getDevicefromOpenstackPort(p); + Port port = getPortFromOpenstackPort(device, p); + Ip4Address vmIp = (Ip4Address) p.fixedIps().values().iterator().next(); + + if (port == null) { + return; + } + + targetList.forEach(routerInterface -> { + OpenstackPort openstackPort = openstackService.port(routerInterface.portId()); + long vni = getVni(openstackPort.networkId()); + + if (vmIp == null) { + return; + } + + populateL3RulestoSameNode(vmIp, p, port, device, vni); + + deviceService.getAvailableDevices().forEach(d -> { + if (!d.equals(device) && !d.equals(getGatewayNode())) { + populateL3RulestoDifferentNode(vmIp, vni, d.id(), getHostIpfromOpenstackPort(p)); + } + }); + + }); + } + + private void populateL3RulestoDifferentNode(Ip4Address vmIp, long vni, DeviceId deviceId, Ip4Address hostIp) { + TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder(); + TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder(); + + sBuilder.matchEthType(Ethernet.TYPE_IPV4) + .matchTunnelId(vni) + .matchIPDst(vmIp.toIpPrefix()); + tBuilder.extension(buildNiciraExtenstion(deviceId, hostIp), deviceId) + .setOutput(getTunnelPort(deviceId)); + + ForwardingObjective fo = DefaultForwardingObjective.builder() + .withSelector(sBuilder.build()) + .withTreatment(tBuilder.build()) + .withPriority(ROUTING_RULE_PRIORITY) + .withFlag(ForwardingObjective.Flag.SPECIFIC) + .fromApp(appId) + .add(); + + flowObjectiveService.forward(deviceId, fo); + } + + private void populateL3RulestoSameNode(Ip4Address vmIp, OpenstackPort p, Port port, Device device, long vni) { + TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder(); + TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder(); + + sBuilder.matchEthType(Ethernet.TYPE_IPV4) + .matchIPDst(vmIp.toIpPrefix()) + .matchTunnelId(vni); + + tBuilder.setEthDst(p.macAddress()) + .setOutput(port.number()); + + ForwardingObjective fo = DefaultForwardingObjective.builder() + .withSelector(sBuilder.build()) + .withTreatment(tBuilder.build()) + .withPriority(ROUTING_RULE_PRIORITY) + .withFlag(ForwardingObjective.Flag.SPECIFIC) + .fromApp(appId) + .add(); + + flowObjectiveService.forward(device.id(), fo); + } + + private Port getPortFromOpenstackPort(Device device, OpenstackPort p) { + String openstackPortName = PORTNAME_PREFIX_VM + p.id().substring(0, 11); + return deviceService.getPorts(device.id()) + .stream() + .filter(pt -> pt.annotations().value(PORTNAME).equals(openstackPortName)) + .findAny() + .orElse(null); + } + + /** + * Removes L3 rules for routerInterface events. + * + * @param vmIp Corresponding Vm ip + * @param routerInterfaces Corresponding routerInterfaces + */ + public void removeL3Rules(Ip4Address vmIp, List routerInterfaces) { + if (vmIp == null) { + return; + } + + OpenstackRoutingService routingService = getService(OpenstackRoutingService.class); + + deviceService.getAvailableDevices().forEach(d -> { + if (!d.equals(getGatewayNode())) { + routerInterfaces.forEach(routerInterface -> { + String networkId = routingService.networkIdForRouterInterface(routerInterface.portId()); + long vni = getVni(networkId); + + TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder(); + + sBuilder.matchEthType(Ethernet.TYPE_IPV4) + .matchIPDst(vmIp.toIpPrefix()) + .matchTunnelId(vni); + + removeRule(d.id(), sBuilder, ForwardingObjective.Flag.SPECIFIC, ROUTING_RULE_PRIORITY); + }); + } + }); + } }