2 * Copyright (c) 2014 - 2016 Red Hat, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.netvirt.openstack.netvirt.impl;
11 import static org.opendaylight.netvirt.openstack.netvirt.api.Action.ADD;
12 import static org.opendaylight.netvirt.openstack.netvirt.api.Action.DELETE;
13 import static org.opendaylight.netvirt.openstack.netvirt.api.Action.UPDATE;
15 import com.google.common.base.Preconditions;
16 import org.apache.commons.lang3.tuple.ImmutablePair;
17 import org.apache.commons.lang3.tuple.Pair;
18 import org.opendaylight.netvirt.openstack.netvirt.AbstractEvent;
19 import org.opendaylight.netvirt.openstack.netvirt.AbstractHandler;
20 import org.opendaylight.netvirt.openstack.netvirt.ConfigInterface;
21 import org.opendaylight.netvirt.openstack.netvirt.NeutronL3AdapterEvent;
22 import org.opendaylight.netvirt.openstack.netvirt.NeutronModelsDataStoreHelper;
23 import org.opendaylight.netvirt.openstack.netvirt.api.Action;
24 import org.opendaylight.netvirt.openstack.netvirt.api.ArpProvider;
25 import org.opendaylight.netvirt.openstack.netvirt.api.ConfigurationService;
26 import org.opendaylight.netvirt.openstack.netvirt.api.Constants;
27 import org.opendaylight.netvirt.openstack.netvirt.api.EventDispatcher;
28 import org.opendaylight.netvirt.openstack.netvirt.api.GatewayMacResolver;
29 import org.opendaylight.netvirt.openstack.netvirt.api.GatewayMacResolverListener;
30 import org.opendaylight.netvirt.openstack.netvirt.api.IcmpEchoProvider;
31 import org.opendaylight.netvirt.openstack.netvirt.api.InboundNatProvider;
32 import org.opendaylight.netvirt.openstack.netvirt.api.L3ForwardingProvider;
33 import org.opendaylight.netvirt.openstack.netvirt.api.NodeCacheManager;
34 import org.opendaylight.netvirt.openstack.netvirt.api.OutboundNatProvider;
35 import org.opendaylight.netvirt.openstack.netvirt.api.RoutingProvider;
36 import org.opendaylight.netvirt.openstack.netvirt.api.SecurityServicesManager;
37 import org.opendaylight.netvirt.openstack.netvirt.api.Southbound;
38 import org.opendaylight.netvirt.openstack.netvirt.api.Status;
39 import org.opendaylight.netvirt.openstack.netvirt.api.StatusCode;
40 import org.opendaylight.netvirt.openstack.netvirt.api.TenantNetworkManager;
41 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronFloatingIP;
42 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronNetwork;
43 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronRouter;
44 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronRouter_Interface;
45 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronSecurityGroup;
46 import org.opendaylight.netvirt.openstack.netvirt.translator.Neutron_IPs;
47 import org.opendaylight.netvirt.openstack.netvirt.translator.crud.INeutronFloatingIPCRUD;
48 import org.opendaylight.netvirt.openstack.netvirt.translator.crud.INeutronNetworkCRUD;
49 import org.opendaylight.netvirt.openstack.netvirt.translator.crud.INeutronPortCRUD;
50 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronPort;
51 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronSubnet;
52 import org.opendaylight.netvirt.openstack.netvirt.translator.crud.INeutronSubnetCRUD;
53 import org.opendaylight.netvirt.openstack.netvirt.translator.iaware.impl.NeutronIAwareUtil;
54 import org.opendaylight.netvirt.utils.servicehelper.ServiceHelper;
55 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
56 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
57 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
58 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.Routers;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
64 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
65 import org.osgi.framework.ServiceReference;
66 import org.slf4j.Logger;
67 import org.slf4j.LoggerFactory;
69 import java.net.Inet4Address;
70 import java.net.InetAddress;
71 import java.net.UnknownHostException;
72 import java.util.ArrayList;
73 import java.util.Collection;
74 import java.util.HashMap;
75 import java.util.Iterator;
76 import java.util.List;
80 * Neutron L3 Adapter implements a hub-like adapter for the various Neutron events. Based on
81 * these events, the abstract router callbacks can be generated to the multi-tenant aware router,
82 * as well as the multi-tenant router forwarding provider.
84 public class NeutronL3Adapter extends AbstractHandler implements GatewayMacResolverListener, ConfigInterface {
85 private static final Logger LOG = LoggerFactory.getLogger(NeutronL3Adapter.class);
87 // The implementation for each of these services is resolved by the OSGi Service Manager
88 private volatile ConfigurationService configurationService;
89 private volatile TenantNetworkManager tenantNetworkManager;
90 private volatile NodeCacheManager nodeCacheManager;
91 private volatile INeutronNetworkCRUD neutronNetworkCache;
92 private volatile INeutronSubnetCRUD neutronSubnetCache;
93 private volatile INeutronPortCRUD neutronPortCache;
94 private volatile INeutronFloatingIPCRUD neutronFloatingIpCache;
95 private volatile L3ForwardingProvider l3ForwardingProvider;
96 private volatile InboundNatProvider inboundNatProvider;
97 private volatile OutboundNatProvider outboundNatProvider;
98 private volatile ArpProvider arpProvider;
99 private volatile RoutingProvider routingProvider;
100 private volatile GatewayMacResolver gatewayMacResolver;
101 private volatile SecurityServicesManager securityServicesManager;
102 private volatile IcmpEchoProvider icmpEchoProvider;
104 private class FloatIpData {
105 // br-int of node where floating ip is associated with tenant port
106 private final Long dpid;
107 // patch port in br-int used to reach br-ex
108 private final Long ofPort;
109 // segmentation id of the net where fixed ip is instantiated
110 private final String segId;
111 // mac address assigned to neutron port of floating ip
112 private final String macAddress;
113 private final String floatingIpAddress;
114 // ip address given to tenant vm
115 private final String fixedIpAddress;
116 private final String neutronRouterMac;
118 FloatIpData(final Long dpid, final Long ofPort, final String segId, final String macAddress,
119 final String floatingIpAddress, final String fixedIpAddress, final String neutronRouterMac) {
121 this.ofPort = ofPort;
123 this.macAddress = macAddress;
124 this.floatingIpAddress = floatingIpAddress;
125 this.fixedIpAddress = fixedIpAddress;
126 this.neutronRouterMac = neutronRouterMac;
130 private Map<String, String> networkIdToRouterMacCache;
131 private Map<String, List<Neutron_IPs>> networkIdToRouterIpListCache;
132 private Map<String, NeutronRouter_Interface> subnetIdToRouterInterfaceCache;
134 private Map<String, Pair<Long, Uuid>> neutronPortToDpIdCache;
135 private Map<String, FloatIpData> floatIpDataMapCache;
137 private String externalRouterMac;
138 private Boolean enabled = false;
139 private Boolean isCachePopulationDone = false;
140 private Map<String, NeutronPort> portCleanupCache;
141 private Map<String, NeutronNetwork> networkCleanupCache;
143 private Southbound southbound;
144 private DistributedArpService distributedArpService;
145 private NeutronModelsDataStoreHelper neutronModelsDataStoreHelper;
147 private static final String OWNER_ROUTER_INTERFACE = "network:router_interface";
148 private static final String OWNER_ROUTER_INTERFACE_DISTRIBUTED = "network:router_interface_distributed";
149 private static final String OWNER_ROUTER_GATEWAY = "network:router_gateway";
150 private static final String OWNER_FLOATING_IP = "network:floatingip";
151 private static final String DEFAULT_EXT_RTR_MAC = "00:00:5E:00:01:01";
153 public NeutronL3Adapter(NeutronModelsDataStoreHelper neutronHelper) {
154 LOG.info(">>>>>> NeutronL3Adapter constructor {}", this.getClass());
155 this.neutronModelsDataStoreHelper = neutronHelper;
158 private void initL3AdapterMembers() {
159 Preconditions.checkNotNull(configurationService);
161 if (configurationService.isL3ForwardingEnabled()) {
162 this.networkIdToRouterMacCache = new HashMap<>();
163 this.networkIdToRouterIpListCache = new HashMap<>();
164 this.subnetIdToRouterInterfaceCache = new HashMap<>();
165 this.neutronPortToDpIdCache = new HashMap<>();
166 this.floatIpDataMapCache = new HashMap<>();
168 this.externalRouterMac = configurationService.getDefaultGatewayMacAddress(null);
169 if (this.externalRouterMac == null) {
170 this.externalRouterMac = DEFAULT_EXT_RTR_MAC;
173 LOG.info("OVSDB L3 forwarding is enabled");
175 LOG.debug("OVSDB L3 forwarding is disabled");
177 this.portCleanupCache = new HashMap<>();
178 this.networkCleanupCache = new HashMap<>();
182 // Callbacks from AbstractHandler
185 public void processEvent(AbstractEvent abstractEvent) {
186 if (!(abstractEvent instanceof NeutronL3AdapterEvent)) {
187 LOG.error("Unable to process abstract event " + abstractEvent);
194 NeutronL3AdapterEvent ev = (NeutronL3AdapterEvent) abstractEvent;
195 switch (ev.getAction()) {
197 if (ev.getSubType() == NeutronL3AdapterEvent.SubType.SUBTYPE_EXTERNAL_MAC_UPDATE) {
198 updateExternalRouterMac( ev.getMacAddress().getValue() );
200 LOG.warn("Received update for an unexpected event " + ev);
210 LOG.warn("Unable to process event " + ev);
216 // Callbacks from GatewayMacResolverListener
220 public void gatewayMacResolved(Long externalNetworkBridgeDpid, IpAddress gatewayIpAddress, MacAddress macAddress) {
221 LOG.info("got gatewayMacResolved callback for ip {} on dpid {} to mac {}",
222 gatewayIpAddress, externalNetworkBridgeDpid, macAddress);
227 if (macAddress == null || macAddress.getValue() == null) {
228 // TODO: handle cases when mac is null
233 // Enqueue event so update is handled by adapter's thread
235 enqueueEvent( new NeutronL3AdapterEvent(externalNetworkBridgeDpid, gatewayIpAddress, macAddress) );
238 private void populateL3ForwardingCaches() {
242 if(this.isCachePopulationDone || this.neutronFloatingIpCache == null
243 || this.neutronPortCache == null ||this.neutronNetworkCache == null) {
246 this.isCachePopulationDone = true;
247 LOG.debug("Populating NetVirt L3 caches from data store configuration");
248 Routers routers = this.neutronModelsDataStoreHelper.readAllNeutronRouters();
249 Ports ports = this.neutronModelsDataStoreHelper.readAllNeutronPorts();
250 if(routers != null && routers.getRouter() != null && ports != null) {
251 LOG.debug("L3 Cache Population : {} Neutron router present in data store",routers.getRouter().size());
252 for( Router router : routers.getRouter()) {
253 LOG.debug("L3 Cache Population : Populate caches for router {}",router);
254 if(!ports.getPort().isEmpty()) {
255 for( Port port : ports.getPort()) {
256 if (port.getDeviceId().equals(router.getUuid().getValue()) &&
257 port.getDeviceOwner().equals(OWNER_ROUTER_INTERFACE)) {
258 LOG.debug("L3 Cache Population : Router interface {} found.",port);
259 networkIdToRouterMacCache.put(port.getNetworkId().getValue()
260 , port.getMacAddress().getValue());
262 networkIdToRouterIpListCache.put(port.getNetworkId().getValue(),
263 NeutronIAwareUtil.convertMDSalIpToNeutronIp(port.getFixedIps()));
264 subnetIdToRouterInterfaceCache.put(port.getFixedIps().get(0).getSubnetId().getValue(),
265 NeutronIAwareUtil.convertMDSalInterfaceToNeutronRouterInterface(port));
269 LOG.warn("L3 Cache Population :Did not find any port information " +
270 "in config Data Store for router {}",router);
274 LOG.debug("NetVirt L3 caches population is done");
277 private Pair<Long, Uuid> getDpIdOfNeutronPort(String neutronTenantPortUuid) {
278 if(neutronPortToDpIdCache.get(neutronTenantPortUuid) == null) {
279 List<Node> bridges = this.southbound.readOvsdbTopologyBridgeNodes();
280 LOG.debug("getDpIdOfNeutronPort : {} bridges present in ovsdb topology",bridges.size());
281 for(Node bridge : bridges) {
282 List<OvsdbTerminationPointAugmentation> interfaces
283 = southbound.extractTerminationPointAugmentations(bridge);
284 if(interfaces != null && !interfaces.isEmpty()) {
285 LOG.debug("getDpIdOfNeutronPort : {} termination point present on bridge {}",
286 interfaces.size(), bridge.getNodeId());
287 for (OvsdbTerminationPointAugmentation intf : interfaces) {
288 NeutronPort neutronPort = tenantNetworkManager.getTenantPort(intf);
289 if(neutronPort != null && neutronPort.getID().equals(neutronTenantPortUuid)) {
290 Long dpId = getDpidForIntegrationBridge(bridge);
291 Uuid interfaceUuid = intf.getInterfaceUuid();
292 LOG.debug("getDpIdOfNeutronPort : Found bridge {} and interface {} for the tenant neutron" +
293 " port {}",dpId,interfaceUuid,neutronTenantPortUuid);
294 handleInterfaceEventAdd(neutronPort.getPortUUID(), dpId, interfaceUuid);
301 return neutronPortToDpIdCache.get(neutronTenantPortUuid);
304 private Collection<FloatIpData> getAllFloatingIPsWithMetadata() {
305 LOG.debug("getAllFloatingIPsWithMetadata : Fechting all floating Ips and it's metadata");
306 List<NeutronFloatingIP> neutronFloatingIps = neutronFloatingIpCache.getAllFloatingIPs();
307 if(neutronFloatingIps != null && !neutronFloatingIps.isEmpty()) {
308 for (NeutronFloatingIP neutronFloatingIP : neutronFloatingIps) {
309 if(!floatIpDataMapCache.containsKey(neutronFloatingIP.getID())){
310 LOG.debug("Metadata for floating ip {} is not present in the cache. " +
311 "Fetching from data store.",neutronFloatingIP.getID());
312 this.getFloatingIPWithMetadata(neutronFloatingIP.getID());
316 LOG.debug("getAllFloatingIPsWithMetadata : {} floating points found in data store",floatIpDataMapCache.size());
317 return floatIpDataMapCache.values();
319 private FloatIpData getFloatingIPWithMetadata(String neutronFloatingId) {
320 LOG.debug("getFloatingIPWithMetadata : Get Floating ip and it's meta data for neutron " +
321 "floating id {} ",neutronFloatingId);
322 if(floatIpDataMapCache.get(neutronFloatingId) == null) {
323 NeutronFloatingIP neutronFloatingIP = neutronFloatingIpCache.getFloatingIP(neutronFloatingId);
324 if (neutronFloatingIP == null) {
325 LOG.error("getFloatingIPWithMetadata : Floating ip {} is missing from data store, that should not happen",neutronFloatingId);
328 List<NeutronPort> neutronPorts = neutronPortCache.getAllPorts();
329 NeutronPort neutronPortForFloatIp = null;
330 for (NeutronPort neutronPort : neutronPorts) {
331 if (neutronPort.getDeviceOwner().equals(OWNER_FLOATING_IP) &&
332 neutronPort.getDeviceID().equals(neutronFloatingIP.getID())) {
333 neutronPortForFloatIp = neutronPort;
338 String neutronTenantPortUuid = neutronFloatingIP.getPortUUID();
339 if(neutronTenantPortUuid == null) {
342 Pair<Long, Uuid> nodeIfPair = this.getDpIdOfNeutronPort(neutronTenantPortUuid);
343 String floatingIpMac = neutronPortForFloatIp == null ? null : neutronPortForFloatIp.getMacAddress();
344 String fixedIpAddress = neutronFloatingIP.getFixedIPAddress();
345 String floatingIpAddress = neutronFloatingIP.getFloatingIPAddress();
347 NeutronPort tenantNeutronPort = neutronPortCache.getPort(neutronTenantPortUuid);
348 NeutronNetwork tenantNeutronNetwork = tenantNeutronPort != null ?
349 neutronNetworkCache.getNetwork(tenantNeutronPort.getNetworkUUID()) : null;
350 String providerSegmentationId = tenantNeutronNetwork != null ?
351 tenantNeutronNetwork.getProviderSegmentationID() : null;
352 String neutronRouterMac = tenantNeutronNetwork != null ?
353 networkIdToRouterMacCache.get(tenantNeutronNetwork.getID()) : null;
355 if (nodeIfPair == null || neutronTenantPortUuid == null ||
356 providerSegmentationId == null || providerSegmentationId.isEmpty() ||
357 floatingIpMac == null || floatingIpMac.isEmpty() ||
358 neutronRouterMac == null || neutronRouterMac.isEmpty()) {
359 LOG.debug("getFloatingIPWithMetadata :Floating IP {}<->{}, incomplete floatPort {} tenantPortUuid {} " +
360 "seg {} mac {} rtrMac {}",
363 neutronPortForFloatIp,
364 neutronTenantPortUuid,
365 providerSegmentationId,
372 // get ofport for patch port in br-int
373 final Long dpId = nodeIfPair.getLeft();
374 final Long ofPort = findOFPortForExtPatch(dpId);
375 if (ofPort == null) {
376 LOG.warn("getFloatingIPWithMetadata : Unable to locate OF port of patch port " +
377 "to connect floating ip to external bridge. dpid {}",
382 final FloatIpData floatIpData = new FloatIpData(dpId, ofPort, providerSegmentationId, floatingIpMac,
383 floatingIpAddress, fixedIpAddress, neutronRouterMac);
384 floatIpDataMapCache.put(neutronFloatingIP.getID(), floatIpData);
387 return floatIpDataMapCache.get(neutronFloatingId);
390 * Invoked to configure the mac address for the external gateway in br-ex. ovsdb netvirt needs help in getting
391 * mac for given ip in br-ex (bug 3378). For example, since ovsdb has no real arp, it needs a service in can
392 * subscribe so that the mac address associated to the gateway ip address is available.
394 * @param externalRouterMacUpdate The mac address to be associated to the gateway.
396 public void updateExternalRouterMac(final String externalRouterMacUpdate) {
397 Preconditions.checkNotNull(externalRouterMacUpdate);
399 flushExistingIpRewrite();
400 this.externalRouterMac = externalRouterMacUpdate;
401 rebuildExistingIpRewrite();
407 * @param action the {@link Action} action to be handled.
408 * @param subnet An instance of NeutronSubnet object.
410 public void handleNeutronSubnetEvent(final NeutronSubnet subnet, Action action) {
411 LOG.debug("Neutron subnet {} event : {}", action, subnet.toString());
413 this.storeNetworkInCleanupCache(neutronNetworkCache.getNetwork(subnet.getNetworkUUID()));
418 * Process the port event as a router interface event.
419 * For a not delete action, since a port is only create when the tennat uses the subnet, it is required to
420 * verify if all routers across all nodes have the interface for the port's subnet(s) configured.
422 * @param action the {@link Action} action to be handled.
423 * @param neutronPort An instance of NeutronPort object.
425 public void handleNeutronPortEvent(final NeutronPort neutronPort, Action action) {
426 LOG.debug("Neutron port {} event : {}", action, neutronPort.toString());
428 if (action == UPDATE) {
429 // FIXME: Bug 4971 Move cleanup cache to SG Impl
430 this.updatePortInCleanupCache(neutronPort, neutronPort.getOriginalPort());
431 if (neutronPort.getPortSecurityEnabled()) {
432 this.processSecurityGroupUpdate(neutronPort);
434 if (isPortSecurityEnableUpdated(neutronPort)) {
435 this.processPortSecurityEnableUpdated(neutronPort);
443 final boolean isDelete = action == DELETE;
445 if (action == DELETE) {
446 // Bug 5164: Cleanup Floating IP OpenFlow Rules when port is deleted.
447 this.cleanupFloatingIPRules(neutronPort);
449 else if (action == UPDATE){
450 // Bug 5353: VM restart cause floatingIp flows to be removed
451 this.updateFloatingIPRules(neutronPort);
454 if (neutronPort.getDeviceOwner().equalsIgnoreCase(OWNER_ROUTER_GATEWAY)){
456 LOG.info("Port {} is network router gateway interface, "
457 + "triggering gateway resolution for the attached external network", neutronPort);
458 this.triggerGatewayMacResolver(neutronPort);
460 NeutronNetwork externalNetwork = neutronNetworkCache.getNetwork(neutronPort.getNetworkUUID());
461 if (null == externalNetwork) {
462 externalNetwork = this.getNetworkFromCleanupCache(neutronPort.getNetworkUUID());
465 if (externalNetwork != null && externalNetwork.isRouterExternal()) {
466 final NeutronSubnet externalSubnet = getExternalNetworkSubnet(neutronPort);
468 if (externalSubnet != null &&
469 externalSubnet.getIpVersion() == 4) {
470 gatewayMacResolver.stopPeriodicRefresh(new Ipv4Address(externalSubnet.getGatewayIP()));
476 // Treat the port event as a router interface event if the port belongs to router. This is a
477 // helper for handling cases when handleNeutronRouterInterfaceEvent is not available
479 if (neutronPort.getDeviceOwner().equalsIgnoreCase(OWNER_ROUTER_INTERFACE) ||
480 neutronPort.getDeviceOwner().equalsIgnoreCase(OWNER_ROUTER_INTERFACE_DISTRIBUTED)) {
482 if (neutronPort.getFixedIPs() != null) {
483 for (Neutron_IPs neutronIP : neutronPort.getFixedIPs()) {
484 NeutronRouter_Interface neutronRouterInterface =
485 new NeutronRouter_Interface(neutronIP.getSubnetUUID(), neutronPort.getPortUUID());
486 // id of router interface to be same as subnet
487 neutronRouterInterface.setID(neutronIP.getSubnetUUID());
488 neutronRouterInterface.setTenantID(neutronPort.getTenantID());
490 this.handleNeutronRouterInterfaceEvent(null /*neutronRouter*/, neutronRouterInterface, action);
494 // We made it here, port is not used as a router interface. If this is not a delete action, make sure that
495 // all nodes that are supposed to have a router interface for the port's subnet(s), have it configured. We
496 // need to do this check here because a router interface is not added to a node until tenant becomes needed
499 if (!isDelete && neutronPort.getFixedIPs() != null) {
500 for (Neutron_IPs neutronIP : neutronPort.getFixedIPs()) {
501 NeutronRouter_Interface neutronRouterInterface =
502 subnetIdToRouterInterfaceCache.get(neutronIP.getSubnetUUID());
503 if (neutronRouterInterface != null) {
504 this.handleNeutronRouterInterfaceEvent(null /*neutronRouter*/, neutronRouterInterface, action);
508 this.updateL3ForNeutronPort(neutronPort, isDelete);
515 * @param action the {@link Action} action to be handled.
516 * @param neutronRouter An instance of NeutronRouter object.
518 public void handleNeutronRouterEvent(final NeutronRouter neutronRouter, Action action) {
519 LOG.debug("Neutron router {} event : {}", action, neutronRouter.toString());
523 * Process the event enforcing actions and verifying dependencies between all router's interface. For example,
524 * delete the ports on the same subnet.
526 * @param action the {@link Action} action to be handled.
527 * @param neutronRouter An instance of NeutronRouter object.
528 * @param neutronRouterInterface An instance of NeutronRouter_Interface object.
530 public void handleNeutronRouterInterfaceEvent(final NeutronRouter neutronRouter,
531 final NeutronRouter_Interface neutronRouterInterface,
533 LOG.debug("Router interface {} got event {}. Subnet {}",
534 neutronRouterInterface.getPortUUID(),
536 neutronRouterInterface.getSubnetUUID());
541 final boolean isDelete = action == DELETE;
543 this.programFlowsForNeutronRouterInterface(neutronRouterInterface, isDelete);
545 // As neutron router interface is added/removed, we need to iterate through all the neutron ports and
546 // see if they are affected by l3
548 for (NeutronPort neutronPort : neutronPortCache.getAllPorts()) {
549 boolean currPortShouldBeDeleted = false;
550 // Note: delete in this case only applies to 1)router interface delete and 2)ports on the same subnet
552 if (neutronPort.getFixedIPs() != null) {
553 for (Neutron_IPs neutronIP : neutronPort.getFixedIPs()) {
554 if (neutronRouterInterface.getSubnetUUID().equalsIgnoreCase(neutronIP.getSubnetUUID())) {
555 currPortShouldBeDeleted = true;
561 this.updateL3ForNeutronPort(neutronPort, currPortShouldBeDeleted);
567 * Invoked when a neutron message regarding the floating ip association is sent to odl via ml2. If the action is
568 * a creation, it will first add ARP rules for the given floating ip and then configure the DNAT (rewrite the
569 * packets from the floating IP address to the internal fixed ip) rules on OpenFlow Table 30 and SNAT rules (other
570 * way around) on OpenFlow Table 100.
572 * @param actionIn the {@link Action} action to be handled.
573 * @param neutronFloatingIP An {@link NeutronFloatingIP} instance of NeutronFloatingIP object.
575 public void handleNeutronFloatingIPEvent(final NeutronFloatingIP neutronFloatingIP,
577 Preconditions.checkNotNull(neutronFloatingIP);
579 LOG.debug(" Floating IP {} {}<->{}, network uuid {}", actionIn,
580 neutronFloatingIP.getFixedIPAddress(),
581 neutronFloatingIP.getFloatingIPAddress(),
582 neutronFloatingIP.getFloatingNetworkUUID());
589 // Consider action to be delete if getFixedIPAddress is null
591 if (neutronFloatingIP.getFixedIPAddress() == null) {
597 // this.programFlowsForFloatingIP(neutronFloatingIP, action == Action.DELETE);
599 if (action != DELETE) {
600 // must be first, as it updates floatIpDataMapCache
601 programFlowsForFloatingIPArpAdd(neutronFloatingIP);
603 programFlowsForFloatingIPInbound(neutronFloatingIP, ADD);
604 programFlowsForFloatingIPOutbound(neutronFloatingIP, ADD);
606 programFlowsForFloatingIPOutbound(neutronFloatingIP, DELETE);
607 programFlowsForFloatingIPInbound(neutronFloatingIP, DELETE);
609 // must be last, as it updates floatIpDataMapCache
610 programFlowsForFloatingIPArpDelete(neutronFloatingIP.getID());
615 * This method performs creation or deletion of in-bound rules into Table 30 for a existing available floating
616 * ip, otherwise for newer one.
618 private void programFlowsForFloatingIPInbound(final NeutronFloatingIP neutronFloatingIP, final Action action) {
619 Preconditions.checkNotNull(neutronFloatingIP);
621 final FloatIpData fid = getFloatingIPWithMetadata(neutronFloatingIP.getID());
623 LOG.trace("programFlowsForFloatingIPInboundAdd {} for {} uuid {} not in local cache",
624 action, neutronFloatingIP.getFloatingIPAddress(), neutronFloatingIP.getID());
627 programInboundIpRewriteStage1(fid.dpid, fid.ofPort, fid.segId, fid.floatingIpAddress, fid.fixedIpAddress,
632 * This method performs creation or deletion of out-bound rules into Table 100 for a existing available floating
633 * ip, otherwise for newer one.
635 private void programFlowsForFloatingIPOutbound(final NeutronFloatingIP neutronFloatingIP, final Action action) {
636 Preconditions.checkNotNull(neutronFloatingIP);
638 final FloatIpData fid = getFloatingIPWithMetadata(neutronFloatingIP.getID());
640 LOG.trace("programFlowsForFloatingIPOutbound {} for {} uuid {} not in local cache",
641 action, neutronFloatingIP.getFloatingIPAddress(), neutronFloatingIP.getID());
644 programOutboundIpRewriteStage1(fid, action);
647 private void flushExistingIpRewrite() {
648 for (FloatIpData fid : getAllFloatingIPsWithMetadata()) {
649 programOutboundIpRewriteStage1(fid, DELETE);
653 private void rebuildExistingIpRewrite() {
654 for (FloatIpData fid : getAllFloatingIPsWithMetadata()) {
655 programOutboundIpRewriteStage1(fid, ADD);
660 * This method creates ARP response rules into OpenFlow Table 30 for a given floating ip. In order to connect
661 * to br-ex from br-int, a patch-port is used. Thus, the patch-port will be responsible to respond the ARP
664 private void programFlowsForFloatingIPArpAdd(final NeutronFloatingIP neutronFloatingIP) {
665 Preconditions.checkNotNull(neutronFloatingIP);
666 Preconditions.checkNotNull(neutronFloatingIP.getFixedIPAddress());
667 Preconditions.checkNotNull(neutronFloatingIP.getFloatingIPAddress());
669 // find bridge Node where floating ip is configured by looking up cache for its port
670 final NeutronPort neutronPortForFloatIp = findNeutronPortForFloatingIp(neutronFloatingIP.getID());
671 final String neutronTenantPortUuid = neutronFloatingIP.getPortUUID();
672 final Pair<Long, Uuid> nodeIfPair = this.getDpIdOfNeutronPort(neutronTenantPortUuid);
673 final String floatingIpMac = neutronPortForFloatIp == null ? null : neutronPortForFloatIp.getMacAddress();
674 final String fixedIpAddress = neutronFloatingIP.getFixedIPAddress();
675 final String floatingIpAddress = neutronFloatingIP.getFloatingIPAddress();
677 final NeutronPort tenantNeutronPort = neutronPortCache.getPort(neutronTenantPortUuid);
678 final NeutronNetwork tenantNeutronNetwork = tenantNeutronPort != null ?
679 neutronNetworkCache.getNetwork(tenantNeutronPort.getNetworkUUID()) : null;
680 final String providerSegmentationId = tenantNeutronNetwork != null ?
681 tenantNeutronNetwork.getProviderSegmentationID() : null;
682 final String neutronRouterMac = tenantNeutronNetwork != null ?
683 networkIdToRouterMacCache.get(tenantNeutronNetwork.getID()) : null;
685 if (nodeIfPair == null || neutronTenantPortUuid == null ||
686 providerSegmentationId == null || providerSegmentationId.isEmpty() ||
687 floatingIpMac == null || floatingIpMac.isEmpty() ||
688 neutronRouterMac == null || neutronRouterMac.isEmpty()) {
689 LOG.trace("Floating IP {}<->{}, incomplete floatPort {} tenantPortUuid {} seg {} mac {} rtrMac {}",
692 neutronPortForFloatIp,
693 neutronTenantPortUuid,
694 providerSegmentationId,
700 // get ofport for patch port in br-int
701 final Long dpId = nodeIfPair.getLeft();
702 final Long ofPort = findOFPortForExtPatch(dpId);
703 if (ofPort == null) {
704 LOG.warn("Unable to locate OF port of patch port to connect floating ip to external bridge. dpid {}",
709 // Respond to ARPs for the floating ip address by default, via the patch port that connects br-int to br-ex
711 if (distributedArpService.programStaticRuleStage1(dpId, encodeExcplicitOFPort(ofPort), floatingIpMac, floatingIpAddress,
713 final FloatIpData floatIpData = new FloatIpData(dpId, ofPort, providerSegmentationId, floatingIpMac,
714 floatingIpAddress, fixedIpAddress, neutronRouterMac);
715 floatIpDataMapCache.put(neutronFloatingIP.getID(), floatIpData);
716 LOG.info("Floating IP {}<->{} programmed ARP mac {} on OFport {} seg {} dpid {}",
717 neutronFloatingIP.getFixedIPAddress(), neutronFloatingIP.getFloatingIPAddress(),
718 floatingIpMac, ofPort, providerSegmentationId, dpId);
722 private void programFlowsForFloatingIPArpDelete(final String neutronFloatingIPUuid) {
723 final FloatIpData floatIpData = getFloatingIPWithMetadata(neutronFloatingIPUuid);
724 if (floatIpData == null) {
725 LOG.trace("programFlowsForFloatingIPArpDelete for uuid {} is not needed", neutronFloatingIPUuid);
729 if (distributedArpService.programStaticRuleStage1(floatIpData.dpid, encodeExcplicitOFPort(floatIpData.ofPort), floatIpData.macAddress,
730 floatIpData.floatingIpAddress, DELETE)) {
731 floatIpDataMapCache.remove(neutronFloatingIPUuid);
732 LOG.info("Floating IP {} un-programmed ARP mac {} on {} dpid {}",
733 floatIpData.floatingIpAddress, floatIpData.macAddress, floatIpData.ofPort, floatIpData.dpid);
737 private NeutronPort findNeutronPortForFloatingIp(final String floatingIpUuid) {
738 for (NeutronPort neutronPort : neutronPortCache.getAllPorts()) {
739 if (neutronPort.getDeviceOwner().equals(OWNER_FLOATING_IP) &&
740 neutronPort.getDeviceID().equals(floatingIpUuid)) {
747 private Long findOFPortForExtPatch(Long dpId) {
748 final String brInt = configurationService.getIntegrationBridgeName();
749 final String brExt = configurationService.getExternalBridgeName();
750 final String portNameInt = configurationService.getPatchPortName(new ImmutablePair<>(brInt, brExt));
752 Preconditions.checkNotNull(dpId);
753 Preconditions.checkNotNull(portNameInt);
755 final long dpidPrimitive = dpId;
756 for (Node node : nodeCacheManager.getBridgeNodes()) {
757 if (dpidPrimitive == southbound.getDataPathId(node)) {
758 final OvsdbTerminationPointAugmentation terminationPointOfBridge =
759 southbound.getTerminationPointOfBridge(node, portNameInt);
760 return terminationPointOfBridge == null ? null : terminationPointOfBridge.getOfport();
769 * @param action the {@link Action} action to be handled.
770 * @param neutronNetwork An {@link NeutronNetwork} instance of NeutronFloatingIP object.
772 public void handleNeutronNetworkEvent(final NeutronNetwork neutronNetwork, Action action) {
773 LOG.debug("neutronNetwork {}: network: {}", action, neutronNetwork);
774 if (action == UPDATE) {
775 this.updateNetworkInCleanupCache(neutronNetwork);
780 // Callbacks from OVSDB's southbound handler
785 * @param bridgeNode An instance of Node object.
786 * @param intf An {@link org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105
787 * .OvsdbTerminationPointAugmentation} instance of OvsdbTerminationPointAugmentation object.
788 * @param neutronNetwork An {@link NeutronNetwork} instance of NeutronNetwork
790 * @param action the {@link Action} action to be handled.
792 public void handleInterfaceEvent(final Node bridgeNode, final OvsdbTerminationPointAugmentation intf,
793 final NeutronNetwork neutronNetwork, Action action) {
794 LOG.debug("southbound interface {} node:{} interface:{}, neutronNetwork:{}",
795 action, bridgeNode.getNodeId().getValue(), intf.getName(), neutronNetwork);
797 final NeutronPort neutronPort = tenantNetworkManager.getTenantPort(intf);
798 if (action != DELETE && neutronPort != null) {
799 // FIXME: Bug 4971 Move cleanup cache to SG Impl
800 storePortInCleanupCache(neutronPort);
807 final Long dpId = getDpidForIntegrationBridge(bridgeNode);
808 final Uuid interfaceUuid = intf.getInterfaceUuid();
810 LOG.trace("southbound interface {} node:{} interface:{}, neutronNetwork:{} port:{} dpid:{} intfUuid:{}",
811 action, bridgeNode.getNodeId().getValue(), intf.getName(), neutronNetwork, neutronPort, dpId, interfaceUuid);
813 if (neutronPort != null) {
814 final String neutronPortUuid = neutronPort.getPortUUID();
816 if (action != DELETE && dpId != null && interfaceUuid != null) {
817 handleInterfaceEventAdd(neutronPortUuid, dpId, interfaceUuid);
820 handleNeutronPortEvent(neutronPort, action);
823 if (action == DELETE && interfaceUuid != null) {
824 handleInterfaceEventDelete(intf, dpId);
828 private void handleInterfaceEventAdd(final String neutronPortUuid, Long dpId, final Uuid interfaceUuid) {
829 neutronPortToDpIdCache.put(neutronPortUuid, new ImmutablePair<>(dpId, interfaceUuid));
830 LOG.debug("handleInterfaceEvent add cache entry NeutronPortUuid {} : dpid {}, ifUuid {}",
831 neutronPortUuid, dpId, interfaceUuid.getValue());
834 private void handleInterfaceEventDelete(final OvsdbTerminationPointAugmentation intf, final Long dpId) {
835 // Remove entry from neutronPortToDpIdCache based on interface uuid
836 for (Map.Entry<String, Pair<Long, Uuid>> entry : neutronPortToDpIdCache.entrySet()) {
837 final String currPortUuid = entry.getKey();
838 if (intf.getInterfaceUuid().equals(entry.getValue().getRight())) {
839 LOG.debug("handleInterfaceEventDelete remove cache entry NeutronPortUuid {} : dpid {}, ifUuid {}",
840 currPortUuid, dpId, intf.getInterfaceUuid().getValue());
841 neutronPortToDpIdCache.remove(currPortUuid);
850 private void updateL3ForNeutronPort(final NeutronPort neutronPort, final boolean isDelete) {
852 final String networkUUID = neutronPort.getNetworkUUID();
853 final String routerMacAddress = networkIdToRouterMacCache.get(networkUUID);
856 // If there is no router interface handling the networkUUID, we are done
857 if (routerMacAddress == null || routerMacAddress.isEmpty()) {
861 // If this is the neutron port for the router interface itself, ignore it as well. Ports that represent the
862 // router interface are handled via handleNeutronRouterInterfaceEvent.
863 if (routerMacAddress.equalsIgnoreCase(neutronPort.getMacAddress())) {
868 final NeutronNetwork neutronNetwork = neutronNetworkCache.getNetwork(networkUUID);
869 final String providerSegmentationId = neutronNetwork != null ?
870 neutronNetwork.getProviderSegmentationID() : null;
871 final String tenantMac = neutronPort.getMacAddress();
873 if (providerSegmentationId == null || providerSegmentationId.isEmpty() ||
874 tenantMac == null || tenantMac.isEmpty()) {
875 // done: go no further w/out all the info needed...
879 final Action action = isDelete ? DELETE : ADD;
880 List<Node> nodes = nodeCacheManager.getBridgeNodes();
881 if (nodes.isEmpty()) {
882 LOG.trace("updateL3ForNeutronPort has no nodes to work with");
884 for (Node node : nodes) {
885 final Long dpid = getDpidForIntegrationBridge(node);
889 if (neutronPort.getFixedIPs() == null) {
892 for (Neutron_IPs neutronIP : neutronPort.getFixedIPs()) {
893 final String tenantIpStr = neutronIP.getIpAddress();
894 if (tenantIpStr.isEmpty()) {
898 // Configure L3 fwd. We do that regardless of tenant network present, because these rules are
899 // still needed when routing to subnets non-local to node (bug 2076).
900 programL3ForwardingStage1(node, dpid, providerSegmentationId, tenantMac, tenantIpStr, action);
905 private void processSecurityGroupUpdate(NeutronPort neutronPort) {
906 LOG.trace("processSecurityGroupUpdate:" + neutronPort);
908 * Get updated data and original data for the the changed. Identify the security groups that got
909 * added and removed and call the appropriate providers for updating the flows.
912 List<NeutronSecurityGroup> addedGroup = getsecurityGroupChanged(neutronPort,
913 neutronPort.getOriginalPort());
914 List<NeutronSecurityGroup> deletedGroup = getsecurityGroupChanged(neutronPort.getOriginalPort(),
917 if (null != addedGroup && !addedGroup.isEmpty()) {
918 securityServicesManager.syncSecurityGroup(neutronPort,addedGroup,true);
920 if (null != deletedGroup && !deletedGroup.isEmpty()) {
921 securityServicesManager.syncSecurityGroup(neutronPort,deletedGroup,false);
924 } catch (Exception e) {
925 LOG.error("Exception in processSecurityGroupUpdate", e);
929 private void processPortSecurityEnableUpdated(NeutronPort neutronPort) {
930 LOG.trace("processPortSecurityEnableUpdated:" + neutronPort);
931 securityServicesManager.syncFixedSecurityGroup(neutronPort,
932 neutronPort.getPortSecurityEnabled());
935 private boolean isPortSecurityEnableUpdated(NeutronPort neutronPort) {
936 LOG.trace("isPortSecuirtyEnableUpdated:" + neutronPort);
937 if (neutronPort != null
938 && neutronPort.getOriginalPort() != null
939 && neutronPort.getOriginalPort().getPortSecurityEnabled() != null
940 && neutronPort.getPortSecurityEnabled() != null
941 && neutronPort.getOriginalPort().getPortSecurityEnabled() != neutronPort
942 .getPortSecurityEnabled()) {
949 private List<NeutronSecurityGroup> getsecurityGroupChanged(NeutronPort port1, NeutronPort port2) {
950 LOG.trace("getsecurityGroupChanged:" + "Port1:" + port1 + "Port2" + port2);
954 List<NeutronSecurityGroup> list1 = new ArrayList<>(port1.getSecurityGroups());
958 List<NeutronSecurityGroup> list2 = new ArrayList<>(port2.getSecurityGroups());
959 for (Iterator<NeutronSecurityGroup> iterator = list1.iterator(); iterator.hasNext();) {
960 NeutronSecurityGroup securityGroup1 = iterator.next();
961 for (NeutronSecurityGroup securityGroup2 :list2) {
962 if (securityGroup1.getID().equals(securityGroup2.getID())) {
970 private void programL3ForwardingStage1(Node node, Long dpid, String providerSegmentationId,
971 String macAddress, String ipStr,
972 Action actionForNode) {
973 if (actionForNode == DELETE) {
974 LOG.trace("Deleting Flow : programL3ForwardingStage1 for node {} providerId {} mac {} ip {} action {}",
975 node.getNodeId().getValue(), providerSegmentationId, macAddress, ipStr, actionForNode);
977 if (actionForNode == ADD) {
978 LOG.trace("Adding Flow : programL3ForwardingStage1 for node {} providerId {} mac {} ip {} action {}",
979 node.getNodeId().getValue(), providerSegmentationId, macAddress, ipStr, actionForNode);
982 this.programL3ForwardingStage2(node, dpid, providerSegmentationId,
983 macAddress, ipStr, actionForNode);
986 private Status programL3ForwardingStage2(Node node, Long dpid, String providerSegmentationId,
989 Action actionForNode) {
992 InetAddress inetAddress = InetAddress.getByName(address);
993 status = l3ForwardingProvider == null ?
994 new Status(StatusCode.SUCCESS) :
995 l3ForwardingProvider.programForwardingTableEntry(dpid, providerSegmentationId,
996 inetAddress, macAddress, actionForNode);
997 } catch (UnknownHostException e) {
998 status = new Status(StatusCode.BADREQUEST);
1001 if (status.isSuccess()) {
1002 LOG.debug("ProgramL3Forwarding {} for mac:{} addr:{} node:{} action:{}",
1003 l3ForwardingProvider == null ? "skipped" : "programmed",
1004 macAddress, address, node.getNodeId().getValue(), actionForNode);
1006 LOG.error("ProgramL3Forwarding failed for mac:{} addr:{} node:{} action:{} status:{}",
1007 macAddress, address, node.getNodeId().getValue(), actionForNode, status);
1014 private void programFlowsForNeutronRouterInterface(final NeutronRouter_Interface destNeutronRouterInterface,
1016 Preconditions.checkNotNull(destNeutronRouterInterface);
1018 final NeutronPort neutronPort = neutronPortCache.getPort(destNeutronRouterInterface.getPortUUID());
1019 String macAddress = neutronPort != null ? neutronPort.getMacAddress() : null;
1020 List<Neutron_IPs> ipList = neutronPort != null ? neutronPort.getFixedIPs() : null;
1021 final NeutronSubnet subnet = neutronSubnetCache.getSubnet(destNeutronRouterInterface.getSubnetUUID());
1022 final NeutronNetwork neutronNetwork = subnet != null ?
1023 neutronNetworkCache.getNetwork(subnet.getNetworkUUID()) : null;
1024 final String destinationSegmentationId = neutronNetwork != null ?
1025 neutronNetwork.getProviderSegmentationID() : null;
1026 final Boolean isExternal = neutronNetwork != null ? neutronNetwork.getRouterExternal() : Boolean.TRUE;
1027 final String cidr = subnet != null ? subnet.getCidr() : null;
1028 final int mask = getMaskLenFromCidr(cidr);
1030 LOG.trace("programFlowsForNeutronRouterInterface called for interface {} isDelete {}",
1031 destNeutronRouterInterface, isDelete);
1033 // in delete path, mac address as well as ip address are not provided. Being so, let's find them from
1035 if (neutronNetwork != null) {
1036 if (macAddress == null || macAddress.isEmpty()) {
1037 macAddress = networkIdToRouterMacCache.get(neutronNetwork.getNetworkUUID());
1039 if (ipList == null || ipList.isEmpty()) {
1040 ipList = networkIdToRouterIpListCache.get(neutronNetwork.getNetworkUUID());
1044 if (destinationSegmentationId == null || destinationSegmentationId.isEmpty() ||
1045 cidr == null || cidr.isEmpty() ||
1046 macAddress == null || macAddress.isEmpty() ||
1047 ipList == null || ipList.isEmpty()) {
1048 LOG.debug("programFlowsForNeutronRouterInterface is bailing seg:{} cidr:{} mac:{} ip:{}",
1049 destinationSegmentationId, cidr, macAddress, ipList);
1050 // done: go no further w/out all the info needed...
1054 final Action actionForNode = isDelete ? DELETE : ADD;
1056 // Keep cache for finding router's mac from network uuid -- add
1059 networkIdToRouterMacCache.put(neutronNetwork.getNetworkUUID(), macAddress);
1060 networkIdToRouterIpListCache.put(neutronNetwork.getNetworkUUID(), new ArrayList<>(ipList));
1061 subnetIdToRouterInterfaceCache.put(subnet.getSubnetUUID(), destNeutronRouterInterface);
1064 List<Node> nodes = nodeCacheManager.getBridgeNodes();
1065 if (nodes.isEmpty()) {
1066 LOG.trace("programFlowsForNeutronRouterInterface has no nodes to work with");
1068 for (Node node : nodes) {
1069 final Long dpid = getDpidForIntegrationBridge(node);
1074 for (Neutron_IPs neutronIP : ipList) {
1075 final String ipStr = neutronIP.getIpAddress();
1076 if (ipStr.isEmpty()) {
1077 LOG.debug("programFlowsForNeutronRouterInterface is skipping node {} ip {}",
1078 node.getNodeId().getValue(), ipStr);
1082 // Iterate through all other interfaces and add/remove reflexive flows to this interface
1084 for (NeutronRouter_Interface srcNeutronRouterInterface : subnetIdToRouterInterfaceCache.values()) {
1085 programFlowsForNeutronRouterInterfacePair(node, dpid,
1086 srcNeutronRouterInterface, destNeutronRouterInterface,
1087 neutronNetwork, destinationSegmentationId,
1088 macAddress, ipStr, mask, actionForNode,
1089 true /*isReflexsive*/);
1093 programFlowForNetworkFromExternal(node, dpid, destinationSegmentationId, macAddress, ipStr, mask,
1096 // Enable ARP responder by default, because router interface needs to be responded always.
1097 distributedArpService.programStaticRuleStage1(dpid, destinationSegmentationId, macAddress, ipStr, actionForNode);
1098 programIcmpEcho(dpid, destinationSegmentationId, macAddress, ipStr, actionForNode);
1101 // Compute action to be programmed. In the case of rewrite exclusions, we must never program rules
1102 // for the external neutron networks.
1105 final Action actionForRewriteExclusion = isExternal ? DELETE : actionForNode;
1106 programIpRewriteExclusionStage1(node, dpid, destinationSegmentationId, cidr, actionForRewriteExclusion);
1111 networkIdToRouterMacCache.remove(neutronNetwork.getNetworkUUID());
1112 networkIdToRouterIpListCache.remove(neutronNetwork.getNetworkUUID());
1113 subnetIdToRouterInterfaceCache.remove(subnet.getSubnetUUID());
1117 private void programFlowForNetworkFromExternal(final Node node,
1119 final String destinationSegmentationId,
1120 final String dstMacAddress,
1121 final String destIpStr,
1123 final Action actionForNode) {
1124 programRouterInterfaceStage1(node, dpid, Constants.EXTERNAL_NETWORK, destinationSegmentationId,
1125 dstMacAddress, destIpStr, destMask, actionForNode);
1128 private void programFlowsForNeutronRouterInterfacePair(final Node node,
1130 final NeutronRouter_Interface srcNeutronRouterInterface,
1131 final NeutronRouter_Interface dstNeutronRouterInterface,
1132 final NeutronNetwork dstNeutronNetwork,
1133 final String destinationSegmentationId,
1134 final String dstMacAddress,
1135 final String destIpStr,
1137 final Action actionForNode,
1138 Boolean isReflexsive) {
1139 Preconditions.checkNotNull(srcNeutronRouterInterface);
1140 Preconditions.checkNotNull(dstNeutronRouterInterface);
1142 final String sourceSubnetId = srcNeutronRouterInterface.getSubnetUUID();
1143 if (sourceSubnetId == null) {
1144 LOG.error("Could not get provider Subnet ID from router interface {}",
1145 srcNeutronRouterInterface.getID());
1149 final NeutronSubnet sourceSubnet = neutronSubnetCache.getSubnet(sourceSubnetId);
1150 final String sourceNetworkId = sourceSubnet == null ? null : sourceSubnet.getNetworkUUID();
1151 if (sourceNetworkId == null) {
1152 LOG.error("Could not get provider Network ID from subnet {}", sourceSubnetId);
1156 final NeutronNetwork sourceNetwork = neutronNetworkCache.getNetwork(sourceNetworkId);
1157 if (sourceNetwork == null) {
1158 LOG.error("Could not get provider Network for Network ID {}", sourceNetworkId);
1162 if (! sourceNetwork.getTenantID().equals(dstNeutronNetwork.getTenantID())) {
1163 // Isolate subnets from different tenants within the same router
1166 final String sourceSegmentationId = sourceNetwork.getProviderSegmentationID();
1167 if (sourceSegmentationId == null) {
1168 LOG.error("Could not get provider Segmentation ID for Subnet {}", sourceSubnetId);
1171 if (sourceSegmentationId.equals(destinationSegmentationId)) {
1176 programRouterInterfaceStage1(node, dpid, sourceSegmentationId, destinationSegmentationId,
1177 dstMacAddress, destIpStr, destMask, actionForNode);
1179 // Flip roles src->dst; dst->src
1181 final NeutronPort sourceNeutronPort = neutronPortCache.getPort(srcNeutronRouterInterface.getPortUUID());
1182 final String macAddress2 = sourceNeutronPort != null ? sourceNeutronPort.getMacAddress() : null;
1183 final List<Neutron_IPs> ipList2 = sourceNeutronPort != null ? sourceNeutronPort.getFixedIPs() : null;
1184 final String cidr2 = sourceSubnet.getCidr();
1185 final int mask2 = getMaskLenFromCidr(cidr2);
1187 if (cidr2 == null || cidr2.isEmpty() ||
1188 macAddress2 == null || macAddress2.isEmpty() ||
1189 ipList2 == null || ipList2.isEmpty()) {
1190 LOG.trace("programFlowsForNeutronRouterInterfacePair reflexive is bailing seg:{} cidr:{} mac:{} ip:{}",
1191 sourceSegmentationId, cidr2, macAddress2, ipList2);
1192 // done: go no further w/out all the info needed...
1196 for (Neutron_IPs neutronIP2 : ipList2) {
1197 final String ipStr2 = neutronIP2.getIpAddress();
1198 if (ipStr2.isEmpty()) {
1201 programFlowsForNeutronRouterInterfacePair(node, dpid, dstNeutronRouterInterface,
1202 srcNeutronRouterInterface,
1203 sourceNetwork, sourceSegmentationId,
1204 macAddress2, ipStr2, mask2, actionForNode,
1205 false /*isReflexsive*/);
1210 private void programRouterInterfaceStage1(Node node, Long dpid, String sourceSegmentationId,
1211 String destinationSegmentationId,
1212 String macAddress, String ipStr, int mask,
1213 Action actionForNode) {
1214 if (actionForNode == DELETE) {
1215 LOG.trace("Deleting Flow : programRouterInterfaceStage1 for node {} sourceSegId {} destSegId {} mac {} ip {} mask {}" +
1217 node.getNodeId().getValue(), sourceSegmentationId, destinationSegmentationId,
1218 macAddress, ipStr, mask, actionForNode);
1220 if (actionForNode == ADD) {
1221 LOG.trace("Adding Flow : programRouterInterfaceStage1 for node {} sourceSegId {} destSegId {} mac {} ip {} mask {}" +
1223 node.getNodeId().getValue(), sourceSegmentationId, destinationSegmentationId,
1224 macAddress, ipStr, mask, actionForNode);
1227 this.programRouterInterfaceStage2(node, dpid, sourceSegmentationId, destinationSegmentationId,
1228 macAddress, ipStr, mask, actionForNode);
1231 private Status programRouterInterfaceStage2(Node node, Long dpid, String sourceSegmentationId,
1232 String destinationSegmentationId,
1234 String address, int mask,
1235 Action actionForNode) {
1238 InetAddress inetAddress = InetAddress.getByName(address);
1239 status = routingProvider == null ?
1240 new Status(StatusCode.SUCCESS) :
1241 routingProvider.programRouterInterface(dpid, sourceSegmentationId, destinationSegmentationId,
1242 macAddress, inetAddress, mask, actionForNode);
1243 } catch (UnknownHostException e) {
1244 status = new Status(StatusCode.BADREQUEST);
1247 if (status.isSuccess()) {
1248 LOG.debug("programRouterInterfaceStage2 {} for mac:{} addr:{}/{} node:{} srcTunId:{} destTunId:{} action:{}",
1249 routingProvider == null ? "skipped" : "programmed",
1250 macAddress, address, mask, node.getNodeId().getValue(), sourceSegmentationId, destinationSegmentationId,
1253 LOG.error("programRouterInterfaceStage2 failed for mac:{} addr:{}/{} node:{} srcTunId:{} destTunId:{} action:{} status:{}",
1254 macAddress, address, mask, node.getNodeId().getValue(), sourceSegmentationId, destinationSegmentationId,
1255 actionForNode, status);
1260 private boolean programIcmpEcho(Long dpid, String segOrOfPort,
1261 String macAddress, String ipStr,
1263 if (action == DELETE ) {
1264 LOG.trace("Deleting Flow : programIcmpEcho dpid {} segOrOfPort {} mac {} ip {} action {}",
1265 dpid, segOrOfPort, macAddress, ipStr, action);
1267 if (action == ADD) {
1268 LOG.trace("Adding Flow : programIcmpEcho dpid {} segOrOfPort {} mac {} ip {} action {}",
1269 dpid, segOrOfPort, macAddress, ipStr, action);
1272 Status status = new Status(StatusCode.UNSUPPORTED);
1273 if (icmpEchoProvider != null){
1275 InetAddress inetAddress = InetAddress.getByName(ipStr);
1276 status = icmpEchoProvider.programIcmpEchoEntry(dpid, segOrOfPort,
1277 macAddress, inetAddress, action);
1278 } catch (UnknownHostException e) {
1279 status = new Status(StatusCode.BADREQUEST);
1283 if (status.isSuccess()) {
1284 LOG.debug("programIcmpEcho {} for mac:{} addr:{} dpid:{} segOrOfPort:{} action:{}",
1285 icmpEchoProvider == null ? "skipped" : "programmed",
1286 macAddress, ipStr, dpid, segOrOfPort, action);
1288 LOG.error("programIcmpEcho failed for mac:{} addr:{} dpid:{} segOrOfPort:{} action:{} status:{}",
1289 macAddress, ipStr, dpid, segOrOfPort, action, status);
1292 return status.isSuccess();
1295 private boolean programInboundIpRewriteStage1(Long dpid, Long inboundOFPort, String providerSegmentationId,
1296 String matchAddress, String rewriteAddress,
1298 if (action == DELETE ) {
1299 LOG.trace("Deleting Flow : programInboundIpRewriteStage1 dpid {} OFPort {} seg {} matchAddress {} rewriteAddress {}" +
1301 dpid, inboundOFPort, providerSegmentationId, matchAddress, rewriteAddress, action);
1303 if (action == ADD ) {
1304 LOG.trace("Adding Flow : programInboundIpRewriteStage1 dpid {} OFPort {} seg {} matchAddress {} rewriteAddress {}" +
1306 dpid, inboundOFPort, providerSegmentationId, matchAddress, rewriteAddress, action);
1309 Status status = programInboundIpRewriteStage2(dpid, inboundOFPort, providerSegmentationId, matchAddress,
1310 rewriteAddress, action);
1311 return status.isSuccess();
1314 private Status programInboundIpRewriteStage2(Long dpid, Long inboundOFPort, String providerSegmentationId,
1315 String matchAddress, String rewriteAddress,
1319 InetAddress inetMatchAddress = InetAddress.getByName(matchAddress);
1320 InetAddress inetRewriteAddress = InetAddress.getByName(rewriteAddress);
1321 status = inboundNatProvider == null ?
1322 new Status(StatusCode.SUCCESS) :
1323 inboundNatProvider.programIpRewriteRule(dpid, inboundOFPort, providerSegmentationId,
1324 inetMatchAddress, inetRewriteAddress,
1326 } catch (UnknownHostException e) {
1327 status = new Status(StatusCode.BADREQUEST);
1330 if (status.isSuccess()) {
1331 final boolean isSkipped = inboundNatProvider == null;
1332 LOG.debug("programInboundIpRewriteStage2 {} for dpid:{} ofPort:{} seg:{} match:{} rewrite:{} action:{}",
1333 isSkipped ? "skipped" : "programmed",
1334 dpid, inboundOFPort, providerSegmentationId, matchAddress, rewriteAddress, action);
1336 LOG.error("programInboundIpRewriteStage2 failed for dpid:{} ofPort:{} seg:{} match:{} rewrite:{} action:{}" +
1338 dpid, inboundOFPort, providerSegmentationId, matchAddress, rewriteAddress, action,
1344 private void programIpRewriteExclusionStage1(Node node, Long dpid, String providerSegmentationId, String cidr,
1345 Action actionForRewriteExclusion) {
1346 if (actionForRewriteExclusion == DELETE ) {
1347 LOG.trace("Deleting Flow : programIpRewriteExclusionStage1 node {} providerId {} cidr {} action {}",
1348 node.getNodeId().getValue(), providerSegmentationId, cidr, actionForRewriteExclusion);
1350 if (actionForRewriteExclusion == ADD) {
1351 LOG.trace("Adding Flow : programIpRewriteExclusionStage1 node {} providerId {} cidr {} action {}",
1352 node.getNodeId().getValue(), providerSegmentationId, cidr, actionForRewriteExclusion);
1355 this.programIpRewriteExclusionStage2(node, dpid, providerSegmentationId, cidr,actionForRewriteExclusion);
1358 private Status programIpRewriteExclusionStage2(Node node, Long dpid, String providerSegmentationId, String cidr,
1359 Action actionForNode) {
1360 final Status status = outboundNatProvider == null ? new Status(StatusCode.SUCCESS) :
1361 outboundNatProvider.programIpRewriteExclusion(dpid, providerSegmentationId, cidr, actionForNode);
1363 if (status.isSuccess()) {
1364 final boolean isSkipped = outboundNatProvider == null;
1365 LOG.debug("IpRewriteExclusion {} for cidr:{} node:{} action:{}",
1366 isSkipped ? "skipped" : "programmed",
1367 cidr, node.getNodeId().getValue(), actionForNode);
1369 LOG.error("IpRewriteExclusion failed for cidr:{} node:{} action:{} status:{}",
1370 cidr, node.getNodeId().getValue(), actionForNode, status);
1375 private void programOutboundIpRewriteStage1(FloatIpData fid, Action action) {
1377 if (action == DELETE) {
1378 LOG.trace("Deleting Flow : programOutboundIpRewriteStage1 dpid {} seg {} fixedIpAddress {} floatIp {} action {} ",
1379 fid.dpid, fid.segId, fid.fixedIpAddress, fid.floatingIpAddress, action);
1381 if (action == ADD) {
1382 LOG.trace("Adding Flow : programOutboundIpRewriteStage1 dpid {} seg {} fixedIpAddress {} floatIp {} action {} " ,
1383 fid.dpid, fid.segId, fid.fixedIpAddress, fid.floatingIpAddress, action);
1386 this.programOutboundIpRewriteStage2(fid, action);
1389 private Status programOutboundIpRewriteStage2(FloatIpData fid, Action action) {
1392 InetAddress matchSrcAddress = InetAddress.getByName(fid.fixedIpAddress);
1393 InetAddress rewriteSrcAddress = InetAddress.getByName(fid.floatingIpAddress);
1394 status = outboundNatProvider == null ?
1395 new Status(StatusCode.SUCCESS) :
1396 outboundNatProvider.programIpRewriteRule(
1397 fid.dpid, fid.segId, fid.neutronRouterMac, matchSrcAddress, fid.macAddress,
1398 this.externalRouterMac, rewriteSrcAddress, fid.ofPort, action);
1399 } catch (UnknownHostException e) {
1400 status = new Status(StatusCode.BADREQUEST);
1403 if (status.isSuccess()) {
1404 final boolean isSkipped = outboundNatProvider == null;
1405 LOG.debug("programOutboundIpRewriteStage2 {} for dpid {} seg {} fixedIpAddress {} floatIp {}" +
1407 isSkipped ? "skipped" : "programmed",
1408 fid.dpid, fid.segId, fid.fixedIpAddress, fid.floatingIpAddress, action);
1410 LOG.error("programOutboundIpRewriteStage2 failed for dpid {} seg {} fixedIpAddress {} floatIp {}" +
1411 " action {} status:{}",
1412 fid.dpid, fid.segId, fid.fixedIpAddress, fid.floatingIpAddress, action, status);
1417 private int getMaskLenFromCidr(String cidr) {
1421 String[] splits = cidr.split("/");
1422 if (splits.length != 2) {
1428 result = Integer.parseInt(splits[1].trim());
1429 } catch (NumberFormatException nfe) {
1435 private Long getDpidForIntegrationBridge(Node node) {
1436 // Check if node is integration bridge; and only then return its dpid
1437 if (southbound.getBridge(node, configurationService.getIntegrationBridgeName()) != null) {
1438 return southbound.getDataPathId(node);
1443 private Long getDpidForExternalBridge(Node node) {
1444 // Check if node is external bridge; and only then return its dpid
1445 if (southbound.getBridge(node, configurationService.getExternalBridgeName()) != null) {
1446 return southbound.getDataPathId(node);
1451 private Node getExternalBridgeNode(){
1452 //Pickup the first node that has external bridge (br-ex).
1453 //NOTE: We are assuming that all the br-ex are serving one external network and gateway ip of
1454 //the external network is reachable from every br-ex
1455 // TODO: Consider other deployment scenario, and thing of better solution.
1456 List<Node> allBridges = nodeCacheManager.getBridgeNodes();
1457 for(Node node : allBridges){
1458 if (southbound.getBridge(node, configurationService.getExternalBridgeName()) != null) {
1465 private NeutronSubnet getExternalNetworkSubnet(NeutronPort gatewayPort){
1466 if (gatewayPort.getFixedIPs() == null) {
1469 for (Neutron_IPs neutronIPs : gatewayPort.getFixedIPs()) {
1470 String subnetUUID = neutronIPs.getSubnetUUID();
1471 NeutronSubnet extSubnet = neutronSubnetCache.getSubnet(subnetUUID);
1472 if (extSubnet != null && extSubnet.getGatewayIP() != null) {
1475 if (extSubnet == null) {
1476 // TODO: when subnet is created, try again.
1477 LOG.debug("subnet {} in not found", subnetUUID);
1483 private void cleanupFloatingIPRules(final NeutronPort neutronPort) {
1484 List<NeutronFloatingIP> neutronFloatingIps = neutronFloatingIpCache.getAllFloatingIPs();
1485 if (neutronFloatingIps != null && !neutronFloatingIps.isEmpty()) {
1486 for (NeutronFloatingIP neutronFloatingIP : neutronFloatingIps) {
1487 // Neutron floating Ip's port uuid cannot be null (Bug#5894)
1488 if (neutronFloatingIP.getPortUUID() != null &&
1489 (neutronFloatingIP.getPortUUID().equals(neutronPort.getPortUUID()))) {
1490 handleNeutronFloatingIPEvent(neutronFloatingIP, DELETE);
1496 private void updateFloatingIPRules(final NeutronPort neutronPort) {
1497 List<NeutronFloatingIP> neutronFloatingIps = neutronFloatingIpCache.getAllFloatingIPs();
1498 if (neutronFloatingIps != null) {
1499 for (NeutronFloatingIP neutronFloatingIP : neutronFloatingIps) {
1500 if (neutronFloatingIP.getPortUUID() != null
1501 && neutronFloatingIP.getPortUUID().equals(
1502 neutronPort.getPortUUID())) {
1503 handleNeutronFloatingIPEvent(neutronFloatingIP, UPDATE);
1510 private void triggerGatewayMacResolver(final NeutronPort gatewayPort){
1512 Preconditions.checkNotNull(gatewayPort);
1513 NeutronNetwork externalNetwork = neutronNetworkCache.getNetwork(gatewayPort.getNetworkUUID());
1515 if(externalNetwork != null){
1516 if(externalNetwork.isRouterExternal()){
1517 final NeutronSubnet externalSubnet = getExternalNetworkSubnet(gatewayPort);
1519 // TODO: address IPv6 case.
1520 if (externalSubnet != null &&
1521 externalSubnet.getIpVersion() == 4 &&
1522 gatewayPort.getFixedIPs() != null) {
1523 LOG.info("Trigger MAC resolution for gateway ip {}", externalSubnet.getGatewayIP());
1524 Neutron_IPs neutronIP = null;
1525 for (Neutron_IPs nIP : gatewayPort.getFixedIPs()) {
1526 InetAddress ipAddress;
1528 ipAddress = InetAddress.getByName(nIP.getIpAddress());
1529 } catch (UnknownHostException e) {
1530 LOG.warn("unknown host exception {}", e);
1533 if (ipAddress instanceof Inet4Address) {
1538 if (neutronIP == null) {
1539 // TODO IPv6 neighbor discovery
1540 LOG.debug("Ignoring gateway ports with IPv6 only fixed ip {}",
1541 gatewayPort.getFixedIPs());
1543 gatewayMacResolver.resolveMacAddress(
1544 this, /* gatewayMacResolverListener */
1545 null, /* externalNetworkBridgeDpid */
1546 true, /* refreshExternalNetworkBridgeDpidIfNeeded */
1547 new Ipv4Address(externalSubnet.getGatewayIP()),
1548 new Ipv4Address(neutronIP.getIpAddress()),
1549 new MacAddress(gatewayPort.getMacAddress()),
1550 true /* periodicRefresh */);
1553 LOG.warn("No gateway IP address found for external network {}", externalNetwork);
1557 LOG.warn("Neutron network not found for router interface {}", gatewayPort);
1562 private void storePortInCleanupCache(NeutronPort port) {
1563 this.portCleanupCache.put(port.getPortUUID(),port);
1567 private void updatePortInCleanupCache(NeutronPort updatedPort,NeutronPort originalPort) {
1568 removePortFromCleanupCache(originalPort);
1569 storePortInCleanupCache(updatedPort);
1572 public void removePortFromCleanupCache(NeutronPort port) {
1574 this.portCleanupCache.remove(port.getPortUUID());
1578 public Map<String, NeutronPort> getPortCleanupCache() {
1579 return this.portCleanupCache;
1582 public NeutronPort getPortFromCleanupCache(String portid) {
1583 for (String neutronPortUuid : this.portCleanupCache.keySet()) {
1584 if (neutronPortUuid.equals(portid)) {
1585 LOG.info("getPortFromCleanupCache: Matching NeutronPort found {}", portid);
1586 return this.portCleanupCache.get(neutronPortUuid);
1592 private void storeNetworkInCleanupCache(NeutronNetwork network) {
1593 this.networkCleanupCache.put(network.getNetworkUUID(), network);
1597 private void updateNetworkInCleanupCache(NeutronNetwork network) {
1598 for (String neutronNetworkUuid:this.networkCleanupCache.keySet()) {
1599 if (neutronNetworkUuid.equals(network.getNetworkUUID())) {
1600 this.networkCleanupCache.remove(neutronNetworkUuid);
1603 this.networkCleanupCache.put(network.getNetworkUUID(), network);
1606 public void removeNetworkFromCleanupCache(String networkid) {
1607 NeutronNetwork network = null;
1608 for (String neutronNetworkUuid:this.networkCleanupCache.keySet()) {
1609 if (neutronNetworkUuid.equals(networkid)) {
1610 network = networkCleanupCache.get(neutronNetworkUuid);
1614 if (network != null) {
1615 for (String neutronPortUuid:this.portCleanupCache.keySet()) {
1616 if (this.portCleanupCache.get(neutronPortUuid).getNetworkUUID().equals(network.getNetworkUUID())) {
1617 LOG.info("This network is used by another port", network);
1621 this.networkCleanupCache.remove(network.getNetworkUUID());
1625 public Map<String, NeutronNetwork> getNetworkCleanupCache() {
1626 return this.networkCleanupCache;
1629 public NeutronNetwork getNetworkFromCleanupCache(String networkid) {
1630 for (String neutronNetworkUuid:this.networkCleanupCache.keySet()) {
1631 if (neutronNetworkUuid.equals(networkid)) {
1632 LOG.info("getPortFromCleanupCache: Matching NeutronPort found {}", networkid);
1633 return networkCleanupCache.get(neutronNetworkUuid);
1639 * Return String that represents OF port with marker explicitly provided (reverse of MatchUtils:parseExplicitOFPort)
1641 * @param ofPort the OF port number
1642 * @return the string with encoded OF port (example format "OFPort|999")
1644 public static String encodeExcplicitOFPort(Long ofPort) {
1645 return "OFPort|" + ofPort.toString();
1647 private void initNetworkCleanUpCache() {
1648 if (this.neutronNetworkCache != null) {
1649 for (NeutronNetwork neutronNetwork : neutronNetworkCache.getAllNetworks()) {
1650 networkCleanupCache.put(neutronNetwork.getNetworkUUID(), neutronNetwork);
1654 private void initPortCleanUpCache() {
1655 if (this.neutronPortCache != null) {
1656 for (NeutronPort neutronPort : neutronPortCache.getAllPorts()) {
1657 portCleanupCache.put(neutronPort.getPortUUID(), neutronPort);
1662 public void setDependencies(ServiceReference serviceReference) {
1664 (EventDispatcher) ServiceHelper.getGlobalInstance(EventDispatcher.class, this);
1665 eventDispatcher.eventHandlerAdded(serviceReference, this);
1666 tenantNetworkManager =
1667 (TenantNetworkManager) ServiceHelper.getGlobalInstance(TenantNetworkManager.class, this);
1668 configurationService =
1669 (ConfigurationService) ServiceHelper.getGlobalInstance(ConfigurationService.class, this);
1671 (ArpProvider) ServiceHelper.getGlobalInstance(ArpProvider.class, this);
1672 inboundNatProvider =
1673 (InboundNatProvider) ServiceHelper.getGlobalInstance(InboundNatProvider.class, this);
1674 outboundNatProvider =
1675 (OutboundNatProvider) ServiceHelper.getGlobalInstance(OutboundNatProvider.class, this);
1677 (RoutingProvider) ServiceHelper.getGlobalInstance(RoutingProvider.class, this);
1678 l3ForwardingProvider =
1679 (L3ForwardingProvider) ServiceHelper.getGlobalInstance(L3ForwardingProvider.class, this);
1680 distributedArpService =
1681 (DistributedArpService) ServiceHelper.getGlobalInstance(DistributedArpService.class, this);
1683 (NodeCacheManager) ServiceHelper.getGlobalInstance(NodeCacheManager.class, this);
1685 (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this);
1686 gatewayMacResolver =
1687 (GatewayMacResolver) ServiceHelper.getGlobalInstance(GatewayMacResolver.class, this);
1688 securityServicesManager =
1689 (SecurityServicesManager) ServiceHelper.getGlobalInstance(SecurityServicesManager.class, this);
1691 initL3AdapterMembers();
1695 public void setDependencies(Object impl) {
1696 if (impl instanceof INeutronNetworkCRUD) {
1697 neutronNetworkCache = (INeutronNetworkCRUD)impl;
1698 initNetworkCleanUpCache();
1699 } else if (impl instanceof INeutronPortCRUD) {
1700 neutronPortCache = (INeutronPortCRUD)impl;
1701 initPortCleanUpCache();
1702 } else if (impl instanceof INeutronSubnetCRUD) {
1703 neutronSubnetCache = (INeutronSubnetCRUD)impl;
1704 } else if (impl instanceof INeutronFloatingIPCRUD) {
1705 neutronFloatingIpCache = (INeutronFloatingIPCRUD)impl;
1706 } else if (impl instanceof ArpProvider) {
1707 arpProvider = (ArpProvider)impl;
1708 } else if (impl instanceof InboundNatProvider) {
1709 inboundNatProvider = (InboundNatProvider)impl;
1710 } else if (impl instanceof OutboundNatProvider) {
1711 outboundNatProvider = (OutboundNatProvider)impl;
1712 } else if (impl instanceof RoutingProvider) {
1713 routingProvider = (RoutingProvider)impl;
1714 } else if (impl instanceof L3ForwardingProvider) {
1715 l3ForwardingProvider = (L3ForwardingProvider)impl;
1716 }else if (impl instanceof GatewayMacResolver) {
1717 gatewayMacResolver = (GatewayMacResolver)impl;
1718 }else if (impl instanceof IcmpEchoProvider) {
1719 icmpEchoProvider = (IcmpEchoProvider)impl;
1722 populateL3ForwardingCaches();