2 * Copyright © 2014, 2017 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.rev130715.IpAddress;
56 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
57 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.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.port.attributes.FixedIps;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
65 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
66 import org.osgi.framework.ServiceReference;
67 import org.slf4j.Logger;
68 import org.slf4j.LoggerFactory;
70 import java.net.Inet4Address;
71 import java.net.InetAddress;
72 import java.net.UnknownHostException;
73 import java.util.ArrayList;
74 import java.util.Collection;
75 import java.util.HashMap;
76 import java.util.Iterator;
77 import java.util.List;
79 import java.util.concurrent.ConcurrentHashMap;
80 import java.util.concurrent.ConcurrentMap;
83 * Neutron L3 Adapter implements a hub-like adapter for the various Neutron events. Based on
84 * these events, the abstract router callbacks can be generated to the multi-tenant aware router,
85 * as well as the multi-tenant router forwarding provider.
87 public class NeutronL3Adapter extends AbstractHandler implements GatewayMacResolverListener, ConfigInterface {
88 private static final Logger LOG = LoggerFactory.getLogger(NeutronL3Adapter.class);
90 // The implementation for each of these services is resolved by the OSGi Service Manager
91 private volatile ConfigurationService configurationService;
92 private volatile TenantNetworkManager tenantNetworkManager;
93 private volatile NodeCacheManager nodeCacheManager;
94 private volatile INeutronNetworkCRUD neutronNetworkCache;
95 private volatile INeutronSubnetCRUD neutronSubnetCache;
96 private volatile INeutronPortCRUD neutronPortCache;
97 private volatile INeutronFloatingIPCRUD neutronFloatingIpCache;
98 private volatile L3ForwardingProvider l3ForwardingProvider;
99 private volatile InboundNatProvider inboundNatProvider;
100 private volatile OutboundNatProvider outboundNatProvider;
101 private volatile ArpProvider arpProvider;
102 private volatile RoutingProvider routingProvider;
103 private volatile GatewayMacResolver gatewayMacResolver;
104 private volatile SecurityServicesManager securityServicesManager;
105 private volatile IcmpEchoProvider icmpEchoProvider;
107 private class FloatIpData {
108 // br-int of node where floating ip is associated with tenant port
109 private final Long dpid;
110 // patch port in br-int used to reach br-ex
111 private final Long ofPort;
112 // segmentation id of the net where fixed ip is instantiated
113 private final String segId;
114 // mac address assigned to neutron port of floating ip
115 private final String macAddress;
116 private final String floatingIpAddress;
117 // ip address given to tenant vm
118 private final String fixedIpAddress;
119 private final String neutronRouterMac;
121 FloatIpData(final Long dpid, final Long ofPort, final String segId, final String macAddress,
122 final String floatingIpAddress, final String fixedIpAddress, final String neutronRouterMac) {
124 this.ofPort = ofPort;
126 this.macAddress = macAddress;
127 this.floatingIpAddress = floatingIpAddress;
128 this.fixedIpAddress = fixedIpAddress;
129 this.neutronRouterMac = neutronRouterMac;
133 private Map<String, String> networkIdToRouterMacCache;
134 private Map<String, List<Neutron_IPs>> networkIdToRouterIpListCache;
135 private Map<String, NeutronRouter_Interface> subnetIdToRouterInterfaceCache;
137 private Map<String, Pair<Long, Uuid>> neutronPortToDpIdCache;
138 private Map<String, FloatIpData> floatIpDataMapCache;
140 private String externalRouterMac;
141 private Boolean enabled = false;
142 private Boolean isCachePopulationDone = false;
143 private ConcurrentMap<String, NeutronPort> portCleanupCache;
144 private ConcurrentMap<String, NeutronNetwork> networkCleanupCache;
146 private Southbound southbound;
147 private DistributedArpService distributedArpService;
148 private NeutronModelsDataStoreHelper neutronModelsDataStoreHelper;
150 private static final String OWNER_ROUTER_INTERFACE = "network:router_interface";
151 private static final String OWNER_ROUTER_INTERFACE_DISTRIBUTED = "network:router_interface_distributed";
152 private static final String OWNER_ROUTER_GATEWAY = "network:router_gateway";
153 private static final String OWNER_FLOATING_IP = "network:floatingip";
154 private static final String DEFAULT_EXT_RTR_MAC = "00:00:5E:00:01:01";
156 public NeutronL3Adapter(NeutronModelsDataStoreHelper neutronHelper) {
157 LOG.info(">>>>>> NeutronL3Adapter constructor {}", this.getClass());
158 this.neutronModelsDataStoreHelper = neutronHelper;
161 private void initL3AdapterMembers() {
162 Preconditions.checkNotNull(configurationService);
164 if (configurationService.isL3ForwardingEnabled()) {
165 this.networkIdToRouterMacCache = new HashMap<>();
166 this.networkIdToRouterIpListCache = new HashMap<>();
167 this.subnetIdToRouterInterfaceCache = new HashMap<>();
168 this.floatIpDataMapCache = new HashMap<>();
170 this.externalRouterMac = configurationService.getDefaultGatewayMacAddress(null);
171 if (this.externalRouterMac == null) {
172 this.externalRouterMac = DEFAULT_EXT_RTR_MAC;
175 LOG.info("OVSDB L3 forwarding is enabled");
177 LOG.debug("OVSDB L3 forwarding is disabled");
179 this.neutronPortToDpIdCache = new HashMap<>();
180 this.portCleanupCache = new ConcurrentHashMap<>();
181 this.networkCleanupCache = new ConcurrentHashMap<>();
185 // Callbacks from AbstractHandler
188 public void processEvent(AbstractEvent abstractEvent) {
189 if (!(abstractEvent instanceof NeutronL3AdapterEvent)) {
190 LOG.error("Unable to process abstract event " + abstractEvent);
197 NeutronL3AdapterEvent ev = (NeutronL3AdapterEvent) abstractEvent;
198 switch (ev.getAction()) {
200 if (ev.getSubType() == NeutronL3AdapterEvent.SubType.SUBTYPE_EXTERNAL_MAC_UPDATE) {
201 updateExternalRouterMac( ev.getMacAddress().getValue() );
203 LOG.warn("Received update for an unexpected event " + ev);
213 LOG.warn("Unable to process event " + ev);
219 // Callbacks from GatewayMacResolverListener
223 public void gatewayMacResolved(Long externalNetworkBridgeDpid, IpAddress gatewayIpAddress, MacAddress macAddress) {
224 LOG.info("got gatewayMacResolved callback for ip {} on dpid {} to mac {}",
225 gatewayIpAddress, externalNetworkBridgeDpid, macAddress);
230 if (macAddress == null || macAddress.getValue() == null) {
231 // TODO: handle cases when mac is null
236 // Enqueue event so update is handled by adapter's thread
238 enqueueEvent( new NeutronL3AdapterEvent(externalNetworkBridgeDpid, gatewayIpAddress, macAddress) );
241 private void populateL3ForwardingCaches() {
245 if(this.isCachePopulationDone || this.neutronFloatingIpCache == null
246 || this.neutronPortCache == null ||this.neutronNetworkCache == null) {
249 this.isCachePopulationDone = true;
250 LOG.debug("Populating NetVirt L3 caches from data store configuration");
251 Routers routers = this.neutronModelsDataStoreHelper.readAllNeutronRouters();
252 Ports ports = this.neutronModelsDataStoreHelper.readAllNeutronPorts();
253 if(routers != null && routers.getRouter() != null && ports != null) {
254 LOG.debug("L3 Cache Population : {} Neutron router present in data store",routers.getRouter().size());
255 for( Router router : routers.getRouter()) {
256 LOG.debug("L3 Cache Population : Populate caches for router {}",router);
257 if(!ports.getPort().isEmpty()) {
258 for( Port port : ports.getPort()) {
259 if (port.getDeviceId().equals(router.getUuid().getValue()) &&
260 port.getDeviceOwner().equals(OWNER_ROUTER_INTERFACE)) {
261 LOG.debug("L3 Cache Population : Router interface {} found.",port);
262 for (final FixedIps fixedIps : port.getFixedIps()) {
263 if (fixedIps.getIpAddress().getIpv4Address() != null) {
264 networkIdToRouterMacCache.put(port.getNetworkId().getValue(),
265 port.getMacAddress().getValue());
266 networkIdToRouterIpListCache.put(port.getNetworkId().getValue(),
267 NeutronIAwareUtil.convertMDSalIpToNeutronIp(port.getFixedIps()));
268 subnetIdToRouterInterfaceCache.put(port.getFixedIps().get(0).getSubnetId().getValue(),
269 NeutronIAwareUtil.convertMDSalInterfaceToNeutronRouterInterface(port));
276 LOG.warn("L3 Cache Population :Did not find any port information " +
277 "in config Data Store for router {}",router);
281 LOG.debug("NetVirt L3 caches population is done");
284 public Pair<Long, Uuid> getDpIdOfNeutronPort(String neutronTenantPortUuid) {
285 if(neutronPortToDpIdCache.get(neutronTenantPortUuid) == null) {
286 List<Node> bridges = this.southbound.readOvsdbTopologyBridgeNodes();
287 LOG.debug("getDpIdOfNeutronPort : {} bridges present in ovsdb topology",bridges.size());
288 for(Node bridge : bridges) {
289 List<OvsdbTerminationPointAugmentation> interfaces
290 = southbound.extractTerminationPointAugmentations(bridge);
291 if(interfaces != null && !interfaces.isEmpty()) {
292 LOG.debug("getDpIdOfNeutronPort : {} termination point present on bridge {}",
293 interfaces.size(), bridge.getNodeId());
294 for (OvsdbTerminationPointAugmentation intf : interfaces) {
295 NeutronPort neutronPort = tenantNetworkManager.getTenantPort(intf);
296 if(neutronPort != null && neutronPort.getID().equals(neutronTenantPortUuid)) {
297 Long dpId = getDpidForIntegrationBridge(bridge);
298 Uuid interfaceUuid = intf.getInterfaceUuid();
299 LOG.debug("getDpIdOfNeutronPort : Found bridge {} and interface {} for the tenant neutron" +
300 " port {}",dpId,interfaceUuid,neutronTenantPortUuid);
301 handleInterfaceEventAdd(neutronPort.getPortUUID(), dpId, interfaceUuid);
308 return neutronPortToDpIdCache.get(neutronTenantPortUuid);
311 private Collection<FloatIpData> getAllFloatingIPsWithMetadata() {
312 LOG.debug("getAllFloatingIPsWithMetadata : Fechting all floating Ips and it's metadata");
313 List<NeutronFloatingIP> neutronFloatingIps = neutronFloatingIpCache.getAllFloatingIPs();
314 if(neutronFloatingIps != null && !neutronFloatingIps.isEmpty()) {
315 for (NeutronFloatingIP neutronFloatingIP : neutronFloatingIps) {
316 if(!floatIpDataMapCache.containsKey(neutronFloatingIP.getID())){
317 LOG.debug("Metadata for floating ip {} is not present in the cache. " +
318 "Fetching from data store.",neutronFloatingIP.getID());
319 this.getFloatingIPWithMetadata(neutronFloatingIP.getID());
323 LOG.debug("getAllFloatingIPsWithMetadata : {} floating points found in data store",floatIpDataMapCache.size());
324 return floatIpDataMapCache.values();
326 private FloatIpData getFloatingIPWithMetadata(String neutronFloatingId) {
327 LOG.debug("getFloatingIPWithMetadata : Get Floating ip and it's meta data for neutron " +
328 "floating id {} ",neutronFloatingId);
329 if(floatIpDataMapCache.get(neutronFloatingId) == null) {
330 NeutronFloatingIP neutronFloatingIP = neutronFloatingIpCache.getFloatingIP(neutronFloatingId);
331 if (neutronFloatingIP == null) {
332 LOG.error("getFloatingIPWithMetadata : Floating ip {} is missing from data store, that should not happen",neutronFloatingId);
335 List<NeutronPort> neutronPorts = neutronPortCache.getAllPorts();
336 NeutronPort neutronPortForFloatIp = null;
337 for (NeutronPort neutronPort : neutronPorts) {
338 if (neutronPort.getDeviceOwner().equals(OWNER_FLOATING_IP) &&
339 neutronPort.getDeviceID().equals(neutronFloatingIP.getID())) {
340 neutronPortForFloatIp = neutronPort;
345 String neutronTenantPortUuid = neutronFloatingIP.getPortUUID();
346 if(neutronTenantPortUuid == null) {
349 Pair<Long, Uuid> nodeIfPair = this.getDpIdOfNeutronPort(neutronTenantPortUuid);
350 String floatingIpMac = neutronPortForFloatIp == null ? null : neutronPortForFloatIp.getMacAddress();
351 String fixedIpAddress = neutronFloatingIP.getFixedIPAddress();
352 String floatingIpAddress = neutronFloatingIP.getFloatingIPAddress();
354 NeutronPort tenantNeutronPort = neutronPortCache.getPort(neutronTenantPortUuid);
355 NeutronNetwork tenantNeutronNetwork = tenantNeutronPort != null ?
356 neutronNetworkCache.getNetwork(tenantNeutronPort.getNetworkUUID()) : null;
357 String providerSegmentationId = tenantNeutronNetwork != null ?
358 tenantNeutronNetwork.getProviderSegmentationID() : null;
359 String neutronRouterMac = tenantNeutronNetwork != null ?
360 networkIdToRouterMacCache.get(tenantNeutronNetwork.getID()) : null;
362 if (nodeIfPair == null || neutronTenantPortUuid == null ||
363 providerSegmentationId == null || providerSegmentationId.isEmpty() ||
364 floatingIpMac == null || floatingIpMac.isEmpty() ||
365 neutronRouterMac == null || neutronRouterMac.isEmpty()) {
366 LOG.debug("getFloatingIPWithMetadata :Floating IP {}<->{}, incomplete floatPort {} tenantPortUuid {} " +
367 "seg {} mac {} rtrMac {}",
370 neutronPortForFloatIp,
371 neutronTenantPortUuid,
372 providerSegmentationId,
379 // get ofport for patch port in br-int
380 final Long dpId = nodeIfPair.getLeft();
381 final Long ofPort = findOFPortForExtPatch(dpId);
382 if (ofPort == null) {
383 LOG.warn("getFloatingIPWithMetadata : Unable to locate OF port of patch port " +
384 "to connect floating ip to external bridge. dpid {}",
389 final FloatIpData floatIpData = new FloatIpData(dpId, ofPort, providerSegmentationId, floatingIpMac,
390 floatingIpAddress, fixedIpAddress, neutronRouterMac);
391 floatIpDataMapCache.put(neutronFloatingIP.getID(), floatIpData);
394 return floatIpDataMapCache.get(neutronFloatingId);
397 * Invoked to configure the mac address for the external gateway in br-ex. ovsdb netvirt needs help in getting
398 * mac for given ip in br-ex (bug 3378). For example, since ovsdb has no real arp, it needs a service in can
399 * subscribe so that the mac address associated to the gateway ip address is available.
401 * @param externalRouterMacUpdate The mac address to be associated to the gateway.
403 public void updateExternalRouterMac(final String externalRouterMacUpdate) {
404 Preconditions.checkNotNull(externalRouterMacUpdate);
406 flushExistingIpRewrite();
407 this.externalRouterMac = externalRouterMacUpdate;
408 rebuildExistingIpRewrite();
414 * @param action the {@link Action} action to be handled.
415 * @param subnet An instance of NeutronSubnet object.
417 public void handleNeutronSubnetEvent(final NeutronSubnet subnet, Action action) {
418 LOG.debug("Neutron subnet {} event : {}", action, subnet.toString());
420 this.storeNetworkInCleanupCache(neutronNetworkCache.getNetwork(subnet.getNetworkUUID()));
425 * Process the port event as a router interface event.
426 * For a not delete action, since a port is only create when the tennat uses the subnet, it is required to
427 * verify if all routers across all nodes have the interface for the port's subnet(s) configured.
429 * @param action the {@link Action} action to be handled.
430 * @param neutronPort An instance of NeutronPort object.
432 public void handleNeutronPortEvent(final NeutronPort neutronPort, Action action) {
433 LOG.debug("Neutron port {} event : {}", action, neutronPort.toString());
435 if (action == UPDATE) {
436 // FIXME: Bug 4971 Move cleanup cache to SG Impl
437 this.updatePortInCleanupCache(neutronPort, neutronPort.getOriginalPort());
438 if (neutronPort.getPortSecurityEnabled()) {
439 this.processSecurityGroupUpdate(neutronPort);
441 if (isPortSecurityEnableUpdated(neutronPort)) {
442 this.processPortSecurityEnableUpdated(neutronPort);
450 final boolean isDelete = action == DELETE;
452 if (action == DELETE) {
453 // Bug 5164: Cleanup Floating IP OpenFlow Rules when port is deleted.
454 this.cleanupFloatingIPRules(neutronPort);
456 else if (action == UPDATE){
457 // Bug 5353: VM restart cause floatingIp flows to be removed
458 this.updateFloatingIPRules(neutronPort);
461 if (neutronPort.getDeviceOwner().equalsIgnoreCase(OWNER_ROUTER_GATEWAY)){
463 LOG.info("Port {} is network router gateway interface, "
464 + "triggering gateway resolution for the attached external network", neutronPort);
465 this.triggerGatewayMacResolver(neutronPort);
467 NeutronNetwork externalNetwork = neutronNetworkCache.getNetwork(neutronPort.getNetworkUUID());
468 if (null == externalNetwork) {
469 externalNetwork = this.getNetworkFromCleanupCache(neutronPort.getNetworkUUID());
472 if (externalNetwork != null && externalNetwork.isRouterExternal()) {
473 final NeutronSubnet externalSubnet = getExternalNetworkSubnet(neutronPort);
475 if (externalSubnet != null &&
476 externalSubnet.getIpVersion() == 4) {
477 gatewayMacResolver.stopPeriodicRefresh(new Ipv4Address(externalSubnet.getGatewayIP()));
483 // Treat the port event as a router interface event if the port belongs to router. This is a
484 // helper for handling cases when handleNeutronRouterInterfaceEvent is not available
486 if (neutronPort.getDeviceOwner().equalsIgnoreCase(OWNER_ROUTER_INTERFACE) ||
487 neutronPort.getDeviceOwner().equalsIgnoreCase(OWNER_ROUTER_INTERFACE_DISTRIBUTED)) {
489 if (neutronPort.getFixedIPs() != null) {
490 for (Neutron_IPs neutronIP : neutronPort.getFixedIPs()) {
491 NeutronRouter_Interface neutronRouterInterface =
492 new NeutronRouter_Interface(neutronIP.getSubnetUUID(), neutronPort.getPortUUID());
493 // id of router interface to be same as subnet
494 neutronRouterInterface.setID(neutronIP.getSubnetUUID());
495 neutronRouterInterface.setTenantID(neutronPort.getTenantID());
497 this.handleNeutronRouterInterfaceEvent(null /*neutronRouter*/, neutronRouterInterface, action);
501 // We made it here, port is not used as a router interface. If this is not a delete action, make sure that
502 // all nodes that are supposed to have a router interface for the port's subnet(s), have it configured. We
503 // need to do this check here because a router interface is not added to a node until tenant becomes needed
506 if (!isDelete && neutronPort.getFixedIPs() != null) {
507 for (Neutron_IPs neutronIP : neutronPort.getFixedIPs()) {
508 NeutronRouter_Interface neutronRouterInterface =
509 subnetIdToRouterInterfaceCache.get(neutronIP.getSubnetUUID());
510 if (neutronRouterInterface != null) {
511 this.handleNeutronRouterInterfaceEvent(null /*neutronRouter*/, neutronRouterInterface, action);
515 this.updateL3ForNeutronPort(neutronPort, isDelete);
522 * @param action the {@link Action} action to be handled.
523 * @param neutronRouter An instance of NeutronRouter object.
525 public void handleNeutronRouterEvent(final NeutronRouter neutronRouter, Action action) {
526 LOG.debug("Neutron router {} event : {}", action, neutronRouter.toString());
530 * Process the event enforcing actions and verifying dependencies between all router's interface. For example,
531 * delete the ports on the same subnet.
533 * @param action the {@link Action} action to be handled.
534 * @param neutronRouter An instance of NeutronRouter object.
535 * @param neutronRouterInterface An instance of NeutronRouter_Interface object.
537 public void handleNeutronRouterInterfaceEvent(final NeutronRouter neutronRouter,
538 final NeutronRouter_Interface neutronRouterInterface,
540 LOG.debug("Router interface {} got event {}. Subnet {}",
541 neutronRouterInterface.getPortUUID(),
543 neutronRouterInterface.getSubnetUUID());
548 final boolean isDelete = action == DELETE;
550 this.programFlowsForNeutronRouterInterface(neutronRouterInterface, isDelete);
552 // As neutron router interface is added/removed, we need to iterate through all the neutron ports and
553 // see if they are affected by l3
555 for (NeutronPort neutronPort : neutronPortCache.getAllPorts()) {
556 boolean currPortShouldBeDeleted = false;
557 // Note: delete in this case only applies to 1)router interface delete and 2)ports on the same subnet
559 if (neutronPort.getFixedIPs() != null) {
560 for (Neutron_IPs neutronIP : neutronPort.getFixedIPs()) {
561 if (neutronRouterInterface.getSubnetUUID().equalsIgnoreCase(neutronIP.getSubnetUUID())) {
562 currPortShouldBeDeleted = true;
568 this.updateL3ForNeutronPort(neutronPort, currPortShouldBeDeleted);
574 * Invoked when a neutron message regarding the floating ip association is sent to odl via ml2. If the action is
575 * a creation, it will first add ARP rules for the given floating ip and then configure the DNAT (rewrite the
576 * packets from the floating IP address to the internal fixed ip) rules on OpenFlow Table 30 and SNAT rules (other
577 * way around) on OpenFlow Table 100.
579 * @param actionIn the {@link Action} action to be handled.
580 * @param neutronFloatingIP An {@link NeutronFloatingIP} instance of NeutronFloatingIP object.
582 public void handleNeutronFloatingIPEvent(final NeutronFloatingIP neutronFloatingIP,
584 Preconditions.checkNotNull(neutronFloatingIP);
586 LOG.debug(" Floating IP {} {}<->{}, network uuid {}", actionIn,
587 neutronFloatingIP.getFixedIPAddress(),
588 neutronFloatingIP.getFloatingIPAddress(),
589 neutronFloatingIP.getFloatingNetworkUUID());
596 // Consider action to be delete if getFixedIPAddress is null
598 if (neutronFloatingIP.getFixedIPAddress() == null) {
604 // this.programFlowsForFloatingIP(neutronFloatingIP, action == Action.DELETE);
606 if (action != DELETE) {
607 // must be first, as it updates floatIpDataMapCache
608 programFlowsForFloatingIPArpAdd(neutronFloatingIP);
610 programFlowsForFloatingIPInbound(neutronFloatingIP, ADD);
611 programFlowsForFloatingIPOutbound(neutronFloatingIP, ADD);
613 programFlowsForFloatingIPOutbound(neutronFloatingIP, DELETE);
614 programFlowsForFloatingIPInbound(neutronFloatingIP, DELETE);
616 // must be last, as it updates floatIpDataMapCache
617 programFlowsForFloatingIPArpDelete(neutronFloatingIP.getID());
622 * This method performs creation or deletion of in-bound rules into Table 30 for a existing available floating
623 * ip, otherwise for newer one.
625 private void programFlowsForFloatingIPInbound(final NeutronFloatingIP neutronFloatingIP, final Action action) {
626 Preconditions.checkNotNull(neutronFloatingIP);
628 final FloatIpData fid = getFloatingIPWithMetadata(neutronFloatingIP.getID());
630 LOG.trace("programFlowsForFloatingIPInboundAdd {} for {} uuid {} not in local cache",
631 action, neutronFloatingIP.getFloatingIPAddress(), neutronFloatingIP.getID());
634 programInboundIpRewriteStage1(fid.dpid, fid.ofPort, fid.segId, fid.floatingIpAddress, fid.fixedIpAddress,
639 * This method performs creation or deletion of out-bound rules into Table 100 for a existing available floating
640 * ip, otherwise for newer one.
642 private void programFlowsForFloatingIPOutbound(final NeutronFloatingIP neutronFloatingIP, final Action action) {
643 Preconditions.checkNotNull(neutronFloatingIP);
645 final FloatIpData fid = getFloatingIPWithMetadata(neutronFloatingIP.getID());
647 LOG.trace("programFlowsForFloatingIPOutbound {} for {} uuid {} not in local cache",
648 action, neutronFloatingIP.getFloatingIPAddress(), neutronFloatingIP.getID());
651 programOutboundIpRewriteStage1(fid, action);
654 private void flushExistingIpRewrite() {
655 for (FloatIpData fid : getAllFloatingIPsWithMetadata()) {
656 programOutboundIpRewriteStage1(fid, DELETE);
660 private void rebuildExistingIpRewrite() {
661 for (FloatIpData fid : getAllFloatingIPsWithMetadata()) {
662 programOutboundIpRewriteStage1(fid, ADD);
667 * This method creates ARP response rules into OpenFlow Table 30 for a given floating ip. In order to connect
668 * to br-ex from br-int, a patch-port is used. Thus, the patch-port will be responsible to respond the ARP
671 private void programFlowsForFloatingIPArpAdd(final NeutronFloatingIP neutronFloatingIP) {
672 Preconditions.checkNotNull(neutronFloatingIP);
673 Preconditions.checkNotNull(neutronFloatingIP.getFixedIPAddress());
674 Preconditions.checkNotNull(neutronFloatingIP.getFloatingIPAddress());
676 // find bridge Node where floating ip is configured by looking up cache for its port
677 final NeutronPort neutronPortForFloatIp = findNeutronPortForFloatingIp(neutronFloatingIP.getID());
678 final String neutronTenantPortUuid = neutronFloatingIP.getPortUUID();
679 final Pair<Long, Uuid> nodeIfPair = this.getDpIdOfNeutronPort(neutronTenantPortUuid);
680 final String floatingIpMac = neutronPortForFloatIp == null ? null : neutronPortForFloatIp.getMacAddress();
681 final String fixedIpAddress = neutronFloatingIP.getFixedIPAddress();
682 final String floatingIpAddress = neutronFloatingIP.getFloatingIPAddress();
684 final NeutronPort tenantNeutronPort = neutronPortCache.getPort(neutronTenantPortUuid);
685 final NeutronNetwork tenantNeutronNetwork = tenantNeutronPort != null ?
686 neutronNetworkCache.getNetwork(tenantNeutronPort.getNetworkUUID()) : null;
687 final String providerSegmentationId = tenantNeutronNetwork != null ?
688 tenantNeutronNetwork.getProviderSegmentationID() : null;
689 final String neutronRouterMac = tenantNeutronNetwork != null ?
690 networkIdToRouterMacCache.get(tenantNeutronNetwork.getID()) : null;
692 if (nodeIfPair == null || neutronTenantPortUuid == null ||
693 providerSegmentationId == null || providerSegmentationId.isEmpty() ||
694 floatingIpMac == null || floatingIpMac.isEmpty() ||
695 neutronRouterMac == null || neutronRouterMac.isEmpty()) {
696 LOG.trace("Floating IP {}<->{}, incomplete floatPort {} tenantPortUuid {} seg {} mac {} rtrMac {}",
699 neutronPortForFloatIp,
700 neutronTenantPortUuid,
701 providerSegmentationId,
707 // get ofport for patch port in br-int
708 final Long dpId = nodeIfPair.getLeft();
709 final Long ofPort = findOFPortForExtPatch(dpId);
710 if (ofPort == null) {
711 LOG.warn("Unable to locate OF port of patch port to connect floating ip to external bridge. dpid {}",
716 // Respond to ARPs for the floating ip address by default, via the patch port that connects br-int to br-ex
718 if (distributedArpService.programStaticRuleStage1(dpId, encodeExcplicitOFPort(ofPort), floatingIpMac, floatingIpAddress,
720 final FloatIpData floatIpData = new FloatIpData(dpId, ofPort, providerSegmentationId, floatingIpMac,
721 floatingIpAddress, fixedIpAddress, neutronRouterMac);
722 floatIpDataMapCache.put(neutronFloatingIP.getID(), floatIpData);
723 LOG.info("Floating IP {}<->{} programmed ARP mac {} on OFport {} seg {} dpid {}",
724 neutronFloatingIP.getFixedIPAddress(), neutronFloatingIP.getFloatingIPAddress(),
725 floatingIpMac, ofPort, providerSegmentationId, dpId);
729 private void programFlowsForFloatingIPArpDelete(final String neutronFloatingIPUuid) {
730 final FloatIpData floatIpData = getFloatingIPWithMetadata(neutronFloatingIPUuid);
731 if (floatIpData == null) {
732 LOG.trace("programFlowsForFloatingIPArpDelete for uuid {} is not needed", neutronFloatingIPUuid);
736 if (distributedArpService.programStaticRuleStage1(floatIpData.dpid, encodeExcplicitOFPort(floatIpData.ofPort), floatIpData.macAddress,
737 floatIpData.floatingIpAddress, DELETE)) {
738 floatIpDataMapCache.remove(neutronFloatingIPUuid);
739 LOG.info("Floating IP {} un-programmed ARP mac {} on {} dpid {}",
740 floatIpData.floatingIpAddress, floatIpData.macAddress, floatIpData.ofPort, floatIpData.dpid);
744 private NeutronPort findNeutronPortForFloatingIp(final String floatingIpUuid) {
745 for (NeutronPort neutronPort : neutronPortCache.getAllPorts()) {
746 if (neutronPort.getDeviceOwner().equals(OWNER_FLOATING_IP) &&
747 neutronPort.getDeviceID().equals(floatingIpUuid)) {
754 private Long findOFPortForExtPatch(Long dpId) {
755 final String brInt = configurationService.getIntegrationBridgeName();
756 final String brExt = configurationService.getExternalBridgeName();
757 final String portNameInt = configurationService.getPatchPortName(new ImmutablePair<>(brInt, brExt));
759 Preconditions.checkNotNull(dpId);
760 Preconditions.checkNotNull(portNameInt);
762 final long dpidPrimitive = dpId;
763 for (Node node : nodeCacheManager.getBridgeNodes()) {
764 if (dpidPrimitive == southbound.getDataPathId(node)) {
765 final OvsdbTerminationPointAugmentation terminationPointOfBridge =
766 southbound.getTerminationPointOfBridge(node, portNameInt);
767 return terminationPointOfBridge == null ? null : terminationPointOfBridge.getOfport();
776 * @param action the {@link Action} action to be handled.
777 * @param neutronNetwork An {@link NeutronNetwork} instance of NeutronFloatingIP object.
779 public void handleNeutronNetworkEvent(final NeutronNetwork neutronNetwork, Action action) {
780 LOG.debug("neutronNetwork {}: network: {}", action, neutronNetwork);
781 if (action == UPDATE) {
782 this.updateNetworkInCleanupCache(neutronNetwork);
787 // Callbacks from OVSDB's southbound handler
792 * @param bridgeNode An instance of Node object.
793 * @param intf An {@link org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105
794 * .OvsdbTerminationPointAugmentation} instance of OvsdbTerminationPointAugmentation object.
795 * @param neutronNetwork An {@link NeutronNetwork} instance of NeutronNetwork
797 * @param action the {@link Action} action to be handled.
799 public void handleInterfaceEvent(final Node bridgeNode, final OvsdbTerminationPointAugmentation intf,
800 final NeutronNetwork neutronNetwork, Action action) {
801 LOG.debug("southbound interface {} node:{} interface:{}, neutronNetwork:{}",
802 action, bridgeNode.getNodeId().getValue(), intf.getName(), neutronNetwork);
804 final NeutronPort neutronPort = tenantNetworkManager.getTenantPort(intf);
805 if (action != DELETE && neutronPort != null) {
806 // FIXME: Bug 4971 Move cleanup cache to SG Impl
807 storePortInCleanupCache(neutronPort);
810 final Long dpId = getDpidForIntegrationBridge(bridgeNode);
811 final Uuid interfaceUuid = intf.getInterfaceUuid();
813 LOG.trace("southbound interface {} node:{} interface:{}, neutronNetwork:{} port:{} dpid:{} intfUuid:{}",
814 action, bridgeNode.getNodeId().getValue(), intf.getName(), neutronNetwork, neutronPort, dpId, interfaceUuid);
816 if (neutronPort != null) {
817 final String neutronPortUuid = neutronPort.getPortUUID();
819 if (action == ADD && dpId != null && interfaceUuid != null) {
820 handleInterfaceEventAdd(neutronPortUuid, dpId, interfaceUuid);
824 handleNeutronPortEvent(neutronPort, action == DELETE ? Action.DELETE : Action.UPDATE);
828 if (action == DELETE && interfaceUuid != null) {
829 handleInterfaceEventDelete(intf, dpId);
833 private void handleInterfaceEventAdd(final String neutronPortUuid, Long dpId, final Uuid interfaceUuid) {
834 neutronPortToDpIdCache.put(neutronPortUuid, new ImmutablePair<>(dpId, interfaceUuid));
835 LOG.debug("handleInterfaceEvent add cache entry NeutronPortUuid {} : dpid {}, ifUuid {}",
836 neutronPortUuid, dpId, interfaceUuid.getValue());
839 private void handleInterfaceEventDelete(final OvsdbTerminationPointAugmentation intf, final Long dpId) {
840 // Remove entry from neutronPortToDpIdCache based on interface uuid
841 for (Map.Entry<String, Pair<Long, Uuid>> entry : neutronPortToDpIdCache.entrySet()) {
842 final String currPortUuid = entry.getKey();
843 if (intf.getInterfaceUuid().equals(entry.getValue().getRight())) {
844 LOG.debug("handleInterfaceEventDelete remove cache entry NeutronPortUuid {} : dpid {}, ifUuid {}",
845 currPortUuid, dpId, intf.getInterfaceUuid().getValue());
846 neutronPortToDpIdCache.remove(currPortUuid);
855 private void updateL3ForNeutronPort(final NeutronPort neutronPort, final boolean isDelete) {
857 final String networkUUID = neutronPort.getNetworkUUID();
858 final String routerMacAddress = networkIdToRouterMacCache.get(networkUUID);
861 // If there is no router interface handling the networkUUID, we are done
862 if (routerMacAddress == null || routerMacAddress.isEmpty()) {
866 // If this is the neutron port for the router interface itself, ignore it as well. Ports that represent the
867 // router interface are handled via handleNeutronRouterInterfaceEvent.
868 if (routerMacAddress.equalsIgnoreCase(neutronPort.getMacAddress())) {
873 final NeutronNetwork neutronNetwork = neutronNetworkCache.getNetwork(networkUUID);
874 final String providerSegmentationId = neutronNetwork != null ?
875 neutronNetwork.getProviderSegmentationID() : null;
876 final String tenantMac = neutronPort.getMacAddress();
878 if (providerSegmentationId == null || providerSegmentationId.isEmpty() ||
879 tenantMac == null || tenantMac.isEmpty()) {
880 // done: go no further w/out all the info needed...
884 final Action action = isDelete ? DELETE : ADD;
885 List<Node> nodes = nodeCacheManager.getBridgeNodes();
886 if (nodes.isEmpty()) {
887 LOG.trace("updateL3ForNeutronPort has no nodes to work with");
889 for (Node node : nodes) {
890 final Long dpid = getDpidForIntegrationBridge(node);
894 if (neutronPort.getFixedIPs() == null) {
897 for (Neutron_IPs neutronIP : neutronPort.getFixedIPs()) {
898 final String tenantIpStr = neutronIP.getIpAddress();
899 if (tenantIpStr.isEmpty()) {
903 // Configure L3 fwd. We do that regardless of tenant network present, because these rules are
904 // still needed when routing to subnets non-local to node (bug 2076).
905 programL3ForwardingStage1(node, dpid, providerSegmentationId, tenantMac, tenantIpStr, action);
910 private void processSecurityGroupUpdate(NeutronPort neutronPort) {
911 LOG.trace("processSecurityGroupUpdate:" + neutronPort);
913 * Get updated data and original data for the the changed. Identify the security groups that got
914 * added and removed and call the appropriate providers for updating the flows.
917 List<NeutronSecurityGroup> addedGroup = getsecurityGroupChanged(neutronPort,
918 neutronPort.getOriginalPort());
919 List<NeutronSecurityGroup> deletedGroup = getsecurityGroupChanged(neutronPort.getOriginalPort(),
922 if (null != deletedGroup && !deletedGroup.isEmpty()) {
923 securityServicesManager.syncSecurityGroup(neutronPort,deletedGroup,false);
925 if (null != addedGroup && !addedGroup.isEmpty()) {
926 securityServicesManager.syncSecurityGroup(neutronPort,addedGroup,true);
929 } catch (Exception e) {
930 LOG.error("Exception in processSecurityGroupUpdate", e);
934 private void processPortSecurityEnableUpdated(NeutronPort neutronPort) {
935 LOG.trace("processPortSecurityEnableUpdated:" + neutronPort);
936 securityServicesManager.syncFixedSecurityGroup(neutronPort,
937 neutronPort.getPortSecurityEnabled());
940 private boolean isPortSecurityEnableUpdated(NeutronPort neutronPort) {
941 LOG.trace("isPortSecurityEnableUpdated: {}", neutronPort);
942 if (neutronPort == null) {
946 NeutronPort originalPort = neutronPort.getOriginalPort();
947 if (originalPort == null) {
951 Boolean originalPortSecurityEnabled = originalPort.getPortSecurityEnabled();
952 if (originalPortSecurityEnabled == null) {
956 return !originalPortSecurityEnabled.equals(neutronPort.getPortSecurityEnabled());
959 private List<NeutronSecurityGroup> getsecurityGroupChanged(NeutronPort port1, NeutronPort port2) {
960 LOG.trace("getsecurityGroupChanged:" + "Port1:" + port1 + "Port2" + port2);
964 List<NeutronSecurityGroup> list1 = new ArrayList<>(port1.getSecurityGroups());
968 List<NeutronSecurityGroup> list2 = new ArrayList<>(port2.getSecurityGroups());
969 for (Iterator<NeutronSecurityGroup> iterator = list1.iterator(); iterator.hasNext();) {
970 NeutronSecurityGroup securityGroup1 = iterator.next();
971 for (NeutronSecurityGroup securityGroup2 :list2) {
972 if (securityGroup1.getID().equals(securityGroup2.getID())) {
980 private void programL3ForwardingStage1(Node node, Long dpid, String providerSegmentationId,
981 String macAddress, String ipStr,
982 Action actionForNode) {
983 if (actionForNode == DELETE) {
984 LOG.trace("Deleting Flow : programL3ForwardingStage1 for node {} providerId {} mac {} ip {} action {}",
985 node.getNodeId().getValue(), providerSegmentationId, macAddress, ipStr, actionForNode);
987 if (actionForNode == ADD) {
988 LOG.trace("Adding Flow : programL3ForwardingStage1 for node {} providerId {} mac {} ip {} action {}",
989 node.getNodeId().getValue(), providerSegmentationId, macAddress, ipStr, actionForNode);
992 this.programL3ForwardingStage2(node, dpid, providerSegmentationId,
993 macAddress, ipStr, actionForNode);
996 private Status programL3ForwardingStage2(Node node, Long dpid, String providerSegmentationId,
999 Action actionForNode) {
1002 InetAddress inetAddress = InetAddress.getByName(address);
1003 status = l3ForwardingProvider == null ?
1004 new Status(StatusCode.SUCCESS) :
1005 l3ForwardingProvider.programForwardingTableEntry(dpid, providerSegmentationId,
1006 inetAddress, macAddress, actionForNode);
1007 } catch (UnknownHostException e) {
1008 status = new Status(StatusCode.BADREQUEST);
1011 if (status.isSuccess()) {
1012 LOG.debug("ProgramL3Forwarding {} for mac:{} addr:{} node:{} action:{}",
1013 l3ForwardingProvider == null ? "skipped" : "programmed",
1014 macAddress, address, node.getNodeId().getValue(), actionForNode);
1016 LOG.error("ProgramL3Forwarding failed for mac:{} addr:{} node:{} action:{} status:{}",
1017 macAddress, address, node.getNodeId().getValue(), actionForNode, status);
1024 private void programFlowsForNeutronRouterInterface(final NeutronRouter_Interface destNeutronRouterInterface,
1026 Preconditions.checkNotNull(destNeutronRouterInterface);
1028 final NeutronPort neutronPort = neutronPortCache.getPort(destNeutronRouterInterface.getPortUUID());
1029 String macAddress = neutronPort != null ? neutronPort.getMacAddress() : null;
1030 List<Neutron_IPs> ipList = neutronPort != null ? neutronPort.getFixedIPs() : null;
1031 final NeutronSubnet subnet = neutronSubnetCache.getSubnet(destNeutronRouterInterface.getSubnetUUID());
1032 final NeutronNetwork neutronNetwork = subnet != null ?
1033 neutronNetworkCache.getNetwork(subnet.getNetworkUUID()) : null;
1034 final String destinationSegmentationId = neutronNetwork != null ?
1035 neutronNetwork.getProviderSegmentationID() : null;
1036 final Boolean isExternal = neutronNetwork != null ? neutronNetwork.getRouterExternal() : Boolean.TRUE;
1037 final String cidr = subnet != null ? subnet.getCidr() : null;
1038 final int mask = getMaskLenFromCidr(cidr);
1040 LOG.trace("programFlowsForNeutronRouterInterface called for interface {} isDelete {}",
1041 destNeutronRouterInterface, isDelete);
1043 if (subnet != null && subnet.getIpVersion() == 6) {
1044 LOG.trace("programFlowsForNeutronRouterInterface doesn't support IPv6 router interface");
1047 // in delete path, mac address as well as ip address are not provided. Being so, let's find them from
1049 if (neutronNetwork != null) {
1050 if (macAddress == null || macAddress.isEmpty()) {
1051 macAddress = networkIdToRouterMacCache.get(neutronNetwork.getNetworkUUID());
1053 if (ipList == null || ipList.isEmpty()) {
1054 ipList = networkIdToRouterIpListCache.get(neutronNetwork.getNetworkUUID());
1058 if (destinationSegmentationId == null || destinationSegmentationId.isEmpty() ||
1059 cidr == null || cidr.isEmpty() ||
1060 macAddress == null || macAddress.isEmpty() ||
1061 ipList == null || ipList.isEmpty()) {
1062 LOG.debug("programFlowsForNeutronRouterInterface is bailing seg:{} cidr:{} mac:{} ip:{}",
1063 destinationSegmentationId, cidr, macAddress, ipList);
1064 // done: go no further w/out all the info needed...
1068 final Action actionForNode = isDelete ? DELETE : ADD;
1070 // Keep cache for finding router's mac from network uuid -- add
1073 networkIdToRouterMacCache.put(neutronNetwork.getNetworkUUID(), macAddress);
1074 networkIdToRouterIpListCache.put(neutronNetwork.getNetworkUUID(), new ArrayList<>(ipList));
1075 subnetIdToRouterInterfaceCache.put(subnet.getSubnetUUID(), destNeutronRouterInterface);
1078 List<Node> nodes = nodeCacheManager.getBridgeNodes();
1079 if (nodes.isEmpty()) {
1080 LOG.trace("programFlowsForNeutronRouterInterface has no nodes to work with");
1082 for (Node node : nodes) {
1083 final Long dpid = getDpidForIntegrationBridge(node);
1088 for (Neutron_IPs neutronIP : ipList) {
1089 final String ipStr = neutronIP.getIpAddress();
1090 if (ipStr.isEmpty()) {
1091 LOG.debug("programFlowsForNeutronRouterInterface is skipping node {} ip {}",
1092 node.getNodeId().getValue(), ipStr);
1095 final IpAddress ipAddress = new IpAddress(ipStr.toCharArray());
1096 if (ipAddress.getIpv4Address() == null) {
1097 LOG.debug("programFlowsForNeutronRouterInterface is skipping node {} ipv6 {}",
1098 node.getNodeId().getValue(), ipStr);
1102 // Iterate through all other interfaces and add/remove reflexive flows to this interface
1104 for (NeutronRouter_Interface srcNeutronRouterInterface : subnetIdToRouterInterfaceCache.values()) {
1105 programFlowsForNeutronRouterInterfacePair(node, dpid,
1106 srcNeutronRouterInterface, destNeutronRouterInterface,
1107 neutronNetwork, destinationSegmentationId,
1108 macAddress, ipStr, mask, actionForNode,
1109 true /*isReflexsive*/);
1113 programFlowForNetworkFromExternal(node, dpid, destinationSegmentationId, macAddress, ipStr, mask,
1116 // Enable ARP responder by default, because router interface needs to be responded always.
1117 distributedArpService.programStaticRuleStage1(dpid, destinationSegmentationId, macAddress, ipStr, actionForNode);
1118 programIcmpEcho(dpid, destinationSegmentationId, macAddress, ipStr, actionForNode);
1121 // Compute action to be programmed. In the case of rewrite exclusions, we must never program rules
1122 // for the external neutron networks.
1125 final Action actionForRewriteExclusion = isExternal ? DELETE : actionForNode;
1126 programIpRewriteExclusionStage1(node, dpid, destinationSegmentationId, cidr, actionForRewriteExclusion);
1131 networkIdToRouterMacCache.remove(neutronNetwork.getNetworkUUID());
1132 networkIdToRouterIpListCache.remove(neutronNetwork.getNetworkUUID());
1133 subnetIdToRouterInterfaceCache.remove(subnet.getSubnetUUID());
1137 private void programFlowForNetworkFromExternal(final Node node,
1139 final String destinationSegmentationId,
1140 final String dstMacAddress,
1141 final String destIpStr,
1143 final Action actionForNode) {
1144 programRouterInterfaceStage1(node, dpid, Constants.EXTERNAL_NETWORK, destinationSegmentationId,
1145 dstMacAddress, destIpStr, destMask, actionForNode);
1148 private void programFlowsForNeutronRouterInterfacePair(final Node node,
1150 final NeutronRouter_Interface srcNeutronRouterInterface,
1151 final NeutronRouter_Interface dstNeutronRouterInterface,
1152 final NeutronNetwork dstNeutronNetwork,
1153 final String destinationSegmentationId,
1154 final String dstMacAddress,
1155 final String destIpStr,
1157 final Action actionForNode,
1158 Boolean isReflexsive) {
1159 Preconditions.checkNotNull(srcNeutronRouterInterface);
1160 Preconditions.checkNotNull(dstNeutronRouterInterface);
1162 final String sourceSubnetId = srcNeutronRouterInterface.getSubnetUUID();
1163 if (sourceSubnetId == null) {
1164 LOG.error("Could not get provider Subnet ID from router interface {}",
1165 srcNeutronRouterInterface.getID());
1169 final NeutronSubnet sourceSubnet = neutronSubnetCache.getSubnet(sourceSubnetId);
1170 final String sourceNetworkId = sourceSubnet == null ? null : sourceSubnet.getNetworkUUID();
1171 if (sourceNetworkId == null) {
1172 LOG.error("Could not get provider Network ID from subnet {}", sourceSubnetId);
1176 final NeutronNetwork sourceNetwork = neutronNetworkCache.getNetwork(sourceNetworkId);
1177 if (sourceNetwork == null) {
1178 LOG.error("Could not get provider Network for Network ID {}", sourceNetworkId);
1182 if (! sourceNetwork.getTenantID().equals(dstNeutronNetwork.getTenantID())) {
1183 // Isolate subnets from different tenants within the same router
1186 final String sourceSegmentationId = sourceNetwork.getProviderSegmentationID();
1187 if (sourceSegmentationId == null) {
1188 LOG.error("Could not get provider Segmentation ID for Subnet {}", sourceSubnetId);
1191 if (sourceSegmentationId.equals(destinationSegmentationId)) {
1196 programRouterInterfaceStage1(node, dpid, sourceSegmentationId, destinationSegmentationId,
1197 dstMacAddress, destIpStr, destMask, actionForNode);
1199 // Flip roles src->dst; dst->src
1201 final NeutronPort sourceNeutronPort = neutronPortCache.getPort(srcNeutronRouterInterface.getPortUUID());
1202 final String macAddress2 = sourceNeutronPort != null ? sourceNeutronPort.getMacAddress() : null;
1203 final List<Neutron_IPs> ipList2 = sourceNeutronPort != null ? sourceNeutronPort.getFixedIPs() : null;
1204 final String cidr2 = sourceSubnet.getCidr();
1205 final int mask2 = getMaskLenFromCidr(cidr2);
1207 if (cidr2 == null || cidr2.isEmpty() ||
1208 macAddress2 == null || macAddress2.isEmpty() ||
1209 ipList2 == null || ipList2.isEmpty()) {
1210 LOG.trace("programFlowsForNeutronRouterInterfacePair reflexive is bailing seg:{} cidr:{} mac:{} ip:{}",
1211 sourceSegmentationId, cidr2, macAddress2, ipList2);
1212 // done: go no further w/out all the info needed...
1216 for (Neutron_IPs neutronIP2 : ipList2) {
1217 final String ipStr2 = neutronIP2.getIpAddress();
1218 if (ipStr2.isEmpty()) {
1221 programFlowsForNeutronRouterInterfacePair(node, dpid, dstNeutronRouterInterface,
1222 srcNeutronRouterInterface,
1223 sourceNetwork, sourceSegmentationId,
1224 macAddress2, ipStr2, mask2, actionForNode,
1225 false /*isReflexsive*/);
1230 private void programRouterInterfaceStage1(Node node, Long dpid, String sourceSegmentationId,
1231 String destinationSegmentationId,
1232 String macAddress, String ipStr, int mask,
1233 Action actionForNode) {
1234 if (actionForNode == DELETE) {
1235 LOG.trace("Deleting Flow : programRouterInterfaceStage1 for node {} sourceSegId {} destSegId {} mac {} ip {} mask {}" +
1237 node.getNodeId().getValue(), sourceSegmentationId, destinationSegmentationId,
1238 macAddress, ipStr, mask, actionForNode);
1240 if (actionForNode == ADD) {
1241 LOG.trace("Adding Flow : programRouterInterfaceStage1 for node {} sourceSegId {} destSegId {} mac {} ip {} mask {}" +
1243 node.getNodeId().getValue(), sourceSegmentationId, destinationSegmentationId,
1244 macAddress, ipStr, mask, actionForNode);
1247 this.programRouterInterfaceStage2(node, dpid, sourceSegmentationId, destinationSegmentationId,
1248 macAddress, ipStr, mask, actionForNode);
1251 private Status programRouterInterfaceStage2(Node node, Long dpid, String sourceSegmentationId,
1252 String destinationSegmentationId,
1254 String address, int mask,
1255 Action actionForNode) {
1258 InetAddress inetAddress = InetAddress.getByName(address);
1259 status = routingProvider == null ?
1260 new Status(StatusCode.SUCCESS) :
1261 routingProvider.programRouterInterface(dpid, sourceSegmentationId, destinationSegmentationId,
1262 macAddress, inetAddress, mask, actionForNode);
1263 } catch (UnknownHostException e) {
1264 status = new Status(StatusCode.BADREQUEST);
1267 if (status.isSuccess()) {
1268 LOG.debug("programRouterInterfaceStage2 {} for mac:{} addr:{}/{} node:{} srcTunId:{} destTunId:{} action:{}",
1269 routingProvider == null ? "skipped" : "programmed",
1270 macAddress, address, mask, node.getNodeId().getValue(), sourceSegmentationId, destinationSegmentationId,
1273 LOG.error("programRouterInterfaceStage2 failed for mac:{} addr:{}/{} node:{} srcTunId:{} destTunId:{} action:{} status:{}",
1274 macAddress, address, mask, node.getNodeId().getValue(), sourceSegmentationId, destinationSegmentationId,
1275 actionForNode, status);
1280 private boolean programIcmpEcho(Long dpid, String segOrOfPort,
1281 String macAddress, String ipStr,
1283 if (action == DELETE ) {
1284 LOG.trace("Deleting Flow : programIcmpEcho dpid {} segOrOfPort {} mac {} ip {} action {}",
1285 dpid, segOrOfPort, macAddress, ipStr, action);
1287 if (action == ADD) {
1288 LOG.trace("Adding Flow : programIcmpEcho dpid {} segOrOfPort {} mac {} ip {} action {}",
1289 dpid, segOrOfPort, macAddress, ipStr, action);
1292 Status status = new Status(StatusCode.UNSUPPORTED);
1293 if (icmpEchoProvider != null){
1295 InetAddress inetAddress = InetAddress.getByName(ipStr);
1296 status = icmpEchoProvider.programIcmpEchoEntry(dpid, segOrOfPort,
1297 macAddress, inetAddress, action);
1298 } catch (UnknownHostException e) {
1299 status = new Status(StatusCode.BADREQUEST);
1303 if (status.isSuccess()) {
1304 LOG.debug("programIcmpEcho {} for mac:{} addr:{} dpid:{} segOrOfPort:{} action:{}",
1305 icmpEchoProvider == null ? "skipped" : "programmed",
1306 macAddress, ipStr, dpid, segOrOfPort, action);
1308 LOG.error("programIcmpEcho failed for mac:{} addr:{} dpid:{} segOrOfPort:{} action:{} status:{}",
1309 macAddress, ipStr, dpid, segOrOfPort, action, status);
1312 return status.isSuccess();
1315 private boolean programInboundIpRewriteStage1(Long dpid, Long inboundOFPort, String providerSegmentationId,
1316 String matchAddress, String rewriteAddress,
1318 if (action == DELETE ) {
1319 LOG.trace("Deleting Flow : programInboundIpRewriteStage1 dpid {} OFPort {} seg {} matchAddress {} rewriteAddress {}" +
1321 dpid, inboundOFPort, providerSegmentationId, matchAddress, rewriteAddress, action);
1323 if (action == ADD ) {
1324 LOG.trace("Adding Flow : programInboundIpRewriteStage1 dpid {} OFPort {} seg {} matchAddress {} rewriteAddress {}" +
1326 dpid, inboundOFPort, providerSegmentationId, matchAddress, rewriteAddress, action);
1329 Status status = programInboundIpRewriteStage2(dpid, inboundOFPort, providerSegmentationId, matchAddress,
1330 rewriteAddress, action);
1331 return status.isSuccess();
1334 private Status programInboundIpRewriteStage2(Long dpid, Long inboundOFPort, String providerSegmentationId,
1335 String matchAddress, String rewriteAddress,
1339 InetAddress inetMatchAddress = InetAddress.getByName(matchAddress);
1340 InetAddress inetRewriteAddress = InetAddress.getByName(rewriteAddress);
1341 status = inboundNatProvider == null ?
1342 new Status(StatusCode.SUCCESS) :
1343 inboundNatProvider.programIpRewriteRule(dpid, inboundOFPort, providerSegmentationId,
1344 inetMatchAddress, inetRewriteAddress,
1346 } catch (UnknownHostException e) {
1347 status = new Status(StatusCode.BADREQUEST);
1350 if (status.isSuccess()) {
1351 final boolean isSkipped = inboundNatProvider == null;
1352 LOG.debug("programInboundIpRewriteStage2 {} for dpid:{} ofPort:{} seg:{} match:{} rewrite:{} action:{}",
1353 isSkipped ? "skipped" : "programmed",
1354 dpid, inboundOFPort, providerSegmentationId, matchAddress, rewriteAddress, action);
1356 LOG.error("programInboundIpRewriteStage2 failed for dpid:{} ofPort:{} seg:{} match:{} rewrite:{} action:{}" +
1358 dpid, inboundOFPort, providerSegmentationId, matchAddress, rewriteAddress, action,
1364 private void programIpRewriteExclusionStage1(Node node, Long dpid, String providerSegmentationId, String cidr,
1365 Action actionForRewriteExclusion) {
1366 if (actionForRewriteExclusion == DELETE ) {
1367 LOG.trace("Deleting Flow : programIpRewriteExclusionStage1 node {} providerId {} cidr {} action {}",
1368 node.getNodeId().getValue(), providerSegmentationId, cidr, actionForRewriteExclusion);
1370 if (actionForRewriteExclusion == ADD) {
1371 LOG.trace("Adding Flow : programIpRewriteExclusionStage1 node {} providerId {} cidr {} action {}",
1372 node.getNodeId().getValue(), providerSegmentationId, cidr, actionForRewriteExclusion);
1375 this.programIpRewriteExclusionStage2(node, dpid, providerSegmentationId, cidr,actionForRewriteExclusion);
1378 private Status programIpRewriteExclusionStage2(Node node, Long dpid, String providerSegmentationId, String cidr,
1379 Action actionForNode) {
1380 final Status status = outboundNatProvider == null ? new Status(StatusCode.SUCCESS) :
1381 outboundNatProvider.programIpRewriteExclusion(dpid, providerSegmentationId, cidr, actionForNode);
1383 if (status.isSuccess()) {
1384 final boolean isSkipped = outboundNatProvider == null;
1385 LOG.debug("IpRewriteExclusion {} for cidr:{} node:{} action:{}",
1386 isSkipped ? "skipped" : "programmed",
1387 cidr, node.getNodeId().getValue(), actionForNode);
1389 LOG.error("IpRewriteExclusion failed for cidr:{} node:{} action:{} status:{}",
1390 cidr, node.getNodeId().getValue(), actionForNode, status);
1395 private void programOutboundIpRewriteStage1(FloatIpData fid, Action action) {
1397 if (action == DELETE) {
1398 LOG.trace("Deleting Flow : programOutboundIpRewriteStage1 dpid {} seg {} fixedIpAddress {} floatIp {} action {} ",
1399 fid.dpid, fid.segId, fid.fixedIpAddress, fid.floatingIpAddress, action);
1401 if (action == ADD) {
1402 LOG.trace("Adding Flow : programOutboundIpRewriteStage1 dpid {} seg {} fixedIpAddress {} floatIp {} action {} " ,
1403 fid.dpid, fid.segId, fid.fixedIpAddress, fid.floatingIpAddress, action);
1406 this.programOutboundIpRewriteStage2(fid, action);
1409 private Status programOutboundIpRewriteStage2(FloatIpData fid, Action action) {
1412 InetAddress matchSrcAddress = InetAddress.getByName(fid.fixedIpAddress);
1413 InetAddress rewriteSrcAddress = InetAddress.getByName(fid.floatingIpAddress);
1414 status = outboundNatProvider == null ?
1415 new Status(StatusCode.SUCCESS) :
1416 outboundNatProvider.programIpRewriteRule(
1417 fid.dpid, fid.segId, fid.neutronRouterMac, matchSrcAddress, fid.macAddress,
1418 this.externalRouterMac, rewriteSrcAddress, fid.ofPort, action);
1419 } catch (UnknownHostException e) {
1420 status = new Status(StatusCode.BADREQUEST);
1423 if (status.isSuccess()) {
1424 final boolean isSkipped = outboundNatProvider == null;
1425 LOG.debug("programOutboundIpRewriteStage2 {} for dpid {} seg {} fixedIpAddress {} floatIp {}" +
1427 isSkipped ? "skipped" : "programmed",
1428 fid.dpid, fid.segId, fid.fixedIpAddress, fid.floatingIpAddress, action);
1430 LOG.error("programOutboundIpRewriteStage2 failed for dpid {} seg {} fixedIpAddress {} floatIp {}" +
1431 " action {} status:{}",
1432 fid.dpid, fid.segId, fid.fixedIpAddress, fid.floatingIpAddress, action, status);
1437 private int getMaskLenFromCidr(String cidr) {
1441 String[] splits = cidr.split("/");
1442 if (splits.length != 2) {
1448 result = Integer.parseInt(splits[1].trim());
1449 } catch (NumberFormatException nfe) {
1455 private Long getDpidForIntegrationBridge(Node node) {
1456 // Check if node is integration bridge; and only then return its dpid
1457 if (southbound.getBridge(node, configurationService.getIntegrationBridgeName()) != null) {
1458 return southbound.getDataPathId(node);
1463 private Long getDpidForExternalBridge(Node node) {
1464 // Check if node is external bridge; and only then return its dpid
1465 if (southbound.getBridge(node, configurationService.getExternalBridgeName()) != null) {
1466 return southbound.getDataPathId(node);
1471 private Node getExternalBridgeNode(){
1472 //Pickup the first node that has external bridge (br-ex).
1473 //NOTE: We are assuming that all the br-ex are serving one external network and gateway ip of
1474 //the external network is reachable from every br-ex
1475 // TODO: Consider other deployment scenario, and thing of better solution.
1476 List<Node> allBridges = nodeCacheManager.getBridgeNodes();
1477 for(Node node : allBridges){
1478 if (southbound.getBridge(node, configurationService.getExternalBridgeName()) != null) {
1485 private NeutronSubnet getExternalNetworkSubnet(NeutronPort gatewayPort){
1486 if (gatewayPort.getFixedIPs() == null) {
1489 for (Neutron_IPs neutronIPs : gatewayPort.getFixedIPs()) {
1490 String subnetUUID = neutronIPs.getSubnetUUID();
1491 NeutronSubnet extSubnet = neutronSubnetCache.getSubnet(subnetUUID);
1492 if (extSubnet != null && extSubnet.getGatewayIP() != null) {
1495 if (extSubnet == null) {
1496 // TODO: when subnet is created, try again.
1497 LOG.debug("subnet {} in not found", subnetUUID);
1503 private void cleanupFloatingIPRules(final NeutronPort neutronPort) {
1504 List<NeutronFloatingIP> neutronFloatingIps = neutronFloatingIpCache.getAllFloatingIPs();
1505 if (neutronFloatingIps != null && !neutronFloatingIps.isEmpty()) {
1506 for (NeutronFloatingIP neutronFloatingIP : neutronFloatingIps) {
1507 // Neutron floating Ip's port uuid cannot be null (Bug#5894)
1508 if (neutronFloatingIP.getPortUUID() != null &&
1509 (neutronFloatingIP.getPortUUID().equals(neutronPort.getPortUUID()))) {
1510 handleNeutronFloatingIPEvent(neutronFloatingIP, DELETE);
1516 private void updateFloatingIPRules(final NeutronPort neutronPort) {
1517 List<NeutronFloatingIP> neutronFloatingIps = neutronFloatingIpCache.getAllFloatingIPs();
1518 if (neutronFloatingIps != null) {
1519 for (NeutronFloatingIP neutronFloatingIP : neutronFloatingIps) {
1520 if (neutronFloatingIP.getPortUUID() != null
1521 && neutronFloatingIP.getPortUUID().equals(
1522 neutronPort.getPortUUID())) {
1523 handleNeutronFloatingIPEvent(neutronFloatingIP, UPDATE);
1530 private void triggerGatewayMacResolver(final NeutronPort gatewayPort){
1532 Preconditions.checkNotNull(gatewayPort);
1533 NeutronNetwork externalNetwork = neutronNetworkCache.getNetwork(gatewayPort.getNetworkUUID());
1535 if(externalNetwork != null){
1536 if(externalNetwork.isRouterExternal()){
1537 final NeutronSubnet externalSubnet = getExternalNetworkSubnet(gatewayPort);
1539 // TODO: address IPv6 case.
1540 if (externalSubnet != null &&
1541 externalSubnet.getIpVersion() == 4 &&
1542 gatewayPort.getFixedIPs() != null) {
1543 LOG.info("Trigger MAC resolution for gateway ip {}", externalSubnet.getGatewayIP());
1544 Neutron_IPs neutronIP = null;
1545 for (Neutron_IPs nIP : gatewayPort.getFixedIPs()) {
1546 InetAddress ipAddress;
1548 ipAddress = InetAddress.getByName(nIP.getIpAddress());
1549 } catch (UnknownHostException e) {
1550 LOG.warn("unknown host exception {}", e);
1553 if (ipAddress instanceof Inet4Address) {
1558 if (neutronIP == null) {
1559 // TODO IPv6 neighbor discovery
1560 LOG.debug("Ignoring gateway ports with IPv6 only fixed ip {}",
1561 gatewayPort.getFixedIPs());
1563 gatewayMacResolver.resolveMacAddress(
1564 this, /* gatewayMacResolverListener */
1565 null, /* externalNetworkBridgeDpid */
1566 true, /* refreshExternalNetworkBridgeDpidIfNeeded */
1567 new Ipv4Address(externalSubnet.getGatewayIP()),
1568 new Ipv4Address(neutronIP.getIpAddress()),
1569 new MacAddress(gatewayPort.getMacAddress()),
1570 true /* periodicRefresh */);
1573 LOG.warn("No gateway IP address found for external network {}", externalNetwork);
1577 LOG.warn("Neutron network not found for router interface {}", gatewayPort);
1582 private void storePortInCleanupCache(NeutronPort port) {
1583 this.portCleanupCache.put(port.getPortUUID(),port);
1587 private void updatePortInCleanupCache(NeutronPort updatedPort,NeutronPort originalPort) {
1588 removePortFromCleanupCache(originalPort);
1589 storePortInCleanupCache(updatedPort);
1592 public void removePortFromCleanupCache(NeutronPort port) {
1594 this.portCleanupCache.remove(port.getPortUUID());
1598 public Map<String, NeutronPort> getPortCleanupCache() {
1599 return this.portCleanupCache;
1602 public NeutronPort getPortFromCleanupCache(String portid) {
1603 NeutronPort ret = this.portCleanupCache.get(portid);
1605 LOG.info("getPortFromCleanupCache: Matching NeutronPort found {}", portid);
1610 private void storeNetworkInCleanupCache(NeutronNetwork network) {
1611 if (network != null) {
1612 this.networkCleanupCache.put(network.getNetworkUUID(), network);
1617 private void updateNetworkInCleanupCache(NeutronNetwork network) {
1618 this.networkCleanupCache.put(network.getNetworkUUID(), network);
1621 public void removeNetworkFromCleanupCache(String networkid) {
1622 NeutronNetwork network = networkCleanupCache.get(networkid);
1623 if (network != null) {
1624 for (NeutronPort port : this.portCleanupCache.values()) {
1625 if (port.getNetworkUUID().equals(networkid)) {
1626 LOG.info("This network is used by another port", network);
1630 this.networkCleanupCache.remove(network.getNetworkUUID());
1634 public NeutronPort getPortPreferablyFromCleanupCache(String portUuid) {
1635 NeutronPort port = getPortFromCleanupCache(portUuid);
1637 port = neutronPortCache.getPort(portUuid);
1639 LOG.warn("In getPortPreferablyFromCleanupCache no neutron port found: portUuid: {}", portUuid);
1645 public Map<String, NeutronNetwork> getNetworkCleanupCache() {
1646 return this.networkCleanupCache;
1649 public NeutronNetwork getNetworkFromCleanupCache(String networkid) {
1650 NeutronNetwork ret = networkCleanupCache.get(networkid);
1652 LOG.info("getNetworkFromCleanupCache: Matching NeutronNetwork found {}", networkid);
1657 * Return String that represents OF port with marker explicitly provided (reverse of MatchUtils:parseExplicitOFPort)
1659 * @param ofPort the OF port number
1660 * @return the string with encoded OF port (example format "OFPort|999")
1662 public static String encodeExcplicitOFPort(Long ofPort) {
1663 return "OFPort|" + ofPort.toString();
1665 private void initNetworkCleanUpCache() {
1666 if (this.neutronNetworkCache != null) {
1667 for (NeutronNetwork neutronNetwork : neutronNetworkCache.getAllNetworks()) {
1668 networkCleanupCache.put(neutronNetwork.getNetworkUUID(), neutronNetwork);
1672 private void initPortCleanUpCache() {
1673 if (this.neutronPortCache != null) {
1674 for (NeutronPort neutronPort : neutronPortCache.getAllPorts()) {
1675 portCleanupCache.put(neutronPort.getPortUUID(), neutronPort);
1680 public void setDependencies(ServiceReference serviceReference) {
1682 (EventDispatcher) ServiceHelper.getGlobalInstance(EventDispatcher.class, this);
1683 eventDispatcher.eventHandlerAdded(serviceReference, this);
1684 tenantNetworkManager =
1685 (TenantNetworkManager) ServiceHelper.getGlobalInstance(TenantNetworkManager.class, this);
1686 configurationService =
1687 (ConfigurationService) ServiceHelper.getGlobalInstance(ConfigurationService.class, this);
1689 (ArpProvider) ServiceHelper.getGlobalInstance(ArpProvider.class, this);
1690 inboundNatProvider =
1691 (InboundNatProvider) ServiceHelper.getGlobalInstance(InboundNatProvider.class, this);
1692 outboundNatProvider =
1693 (OutboundNatProvider) ServiceHelper.getGlobalInstance(OutboundNatProvider.class, this);
1695 (RoutingProvider) ServiceHelper.getGlobalInstance(RoutingProvider.class, this);
1696 l3ForwardingProvider =
1697 (L3ForwardingProvider) ServiceHelper.getGlobalInstance(L3ForwardingProvider.class, this);
1698 distributedArpService =
1699 (DistributedArpService) ServiceHelper.getGlobalInstance(DistributedArpService.class, this);
1701 (NodeCacheManager) ServiceHelper.getGlobalInstance(NodeCacheManager.class, this);
1703 (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this);
1704 gatewayMacResolver =
1705 (GatewayMacResolver) ServiceHelper.getGlobalInstance(GatewayMacResolver.class, this);
1706 securityServicesManager =
1707 (SecurityServicesManager) ServiceHelper.getGlobalInstance(SecurityServicesManager.class, this);
1709 initL3AdapterMembers();
1713 public void setDependencies(Object impl) {
1714 if (impl instanceof INeutronNetworkCRUD) {
1715 neutronNetworkCache = (INeutronNetworkCRUD)impl;
1716 initNetworkCleanUpCache();
1717 } else if (impl instanceof INeutronPortCRUD) {
1718 neutronPortCache = (INeutronPortCRUD)impl;
1719 initPortCleanUpCache();
1720 } else if (impl instanceof INeutronSubnetCRUD) {
1721 neutronSubnetCache = (INeutronSubnetCRUD)impl;
1722 } else if (impl instanceof INeutronFloatingIPCRUD) {
1723 neutronFloatingIpCache = (INeutronFloatingIPCRUD)impl;
1724 } else if (impl instanceof ArpProvider) {
1725 arpProvider = (ArpProvider)impl;
1726 } else if (impl instanceof InboundNatProvider) {
1727 inboundNatProvider = (InboundNatProvider)impl;
1728 } else if (impl instanceof OutboundNatProvider) {
1729 outboundNatProvider = (OutboundNatProvider)impl;
1730 } else if (impl instanceof RoutingProvider) {
1731 routingProvider = (RoutingProvider)impl;
1732 } else if (impl instanceof L3ForwardingProvider) {
1733 l3ForwardingProvider = (L3ForwardingProvider)impl;
1734 }else if (impl instanceof GatewayMacResolver) {
1735 gatewayMacResolver = (GatewayMacResolver)impl;
1736 }else if (impl instanceof IcmpEchoProvider) {
1737 icmpEchoProvider = (IcmpEchoProvider)impl;
1740 populateL3ForwardingCaches();