2 * Copyright (c) 2016, 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
8 package org.opendaylight.netvirt.ipv6service;
10 import java.util.Collections;
11 import java.util.List;
12 import javax.annotation.PreDestroy;
13 import javax.inject.Inject;
14 import javax.inject.Singleton;
15 import org.opendaylight.genius.mdsalutil.MDSALUtil;
16 import org.opendaylight.genius.mdsalutil.NwConstants;
17 import org.opendaylight.genius.utils.SystemPropertyReader;
18 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
19 import org.opendaylight.infrautils.utils.concurrent.Executors;
20 import org.opendaylight.mdsal.binding.api.DataBroker;
21 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
22 import org.opendaylight.netvirt.ipv6service.utils.Ipv6ServiceConstants;
23 import org.opendaylight.netvirt.ipv6service.utils.Ipv6ServiceUtils;
24 import org.opendaylight.serviceutils.tools.listener.AbstractClusteredAsyncDataTreeChangeListener;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev170119.L2vlan;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
28 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
30 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
31 import org.opendaylight.yangtools.yang.common.Uint64;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
36 public class Ipv6ServiceInterfaceEventListener
37 extends AbstractClusteredAsyncDataTreeChangeListener<Interface> {
38 private static final Logger LOG = LoggerFactory.getLogger(Ipv6ServiceInterfaceEventListener.class);
39 private final DataBroker dataBroker;
40 private final IfMgr ifMgr;
41 private final Ipv6ServiceUtils ipv6ServiceUtils;
42 private final JobCoordinator jobCoordinator;
43 private final Ipv6ServiceEosHandler ipv6ServiceEosHandler;
46 * Intialize the member variables.
47 * @param broker the data broker instance.
50 public Ipv6ServiceInterfaceEventListener(DataBroker broker, IfMgr ifMgr, Ipv6ServiceUtils ipv6ServiceUtils,
51 final JobCoordinator jobCoordinator, Ipv6ServiceEosHandler ipv6ServiceEosHandler) {
52 super(broker, LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(InterfacesState.class)
53 .child(Interface.class),
54 Executors.newListeningSingleThreadExecutor("Ipv6ServiceInterfaceEventListener", LOG));
55 this.dataBroker = broker;
57 this.ipv6ServiceUtils = ipv6ServiceUtils;
58 this.jobCoordinator = jobCoordinator;
59 this.ipv6ServiceEosHandler = ipv6ServiceEosHandler;
63 LOG.info("{} init", getClass().getSimpleName());
70 Executors.shutdownAndAwaitTermination(getExecutorService());
74 public void remove(InstanceIdentifier<Interface> key, Interface del) {
75 LOG.debug("Port removed {}, {}", key, del);
76 if (!L2vlan.class.equals(del.getType())) {
80 // In ipv6service, we are only interested in the notification for NeutronPort, so we skip other notifications
81 List<String> ofportIds = del.getLowerLayerIf();
82 if (ofportIds == null || ofportIds.isEmpty() || !isNeutronPort(del.getName())) {
86 if (!ipv6ServiceEosHandler.isClusterOwner()) {
87 LOG.trace("Not a cluster Owner, skipping further IPv6 processing on this node.");
90 Uuid portId = new Uuid(del.getName());
91 VirtualPort port = ifMgr.obtainV6Interface(portId);
93 LOG.info("Port {} does not include IPv6Address, skipping.", portId);
97 if (port.getServiceBindingStatus()) {
98 jobCoordinator.enqueueJob("IPv6-" + String.valueOf(portId), () -> {
100 ipv6ServiceUtils.unbindIpv6Service(portId.getValue());
101 port.setServiceBindingStatus(false);
102 return Collections.emptyList();
103 }, SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
106 VirtualPort routerPort = ifMgr.getRouterV6InterfaceForNetwork(port.getNetworkID());
107 ifMgr.handleInterfaceStateEvent(port, ipv6ServiceUtils.getDpIdFromInterfaceState(del), routerPort,
108 Ipv6ServiceConstants.DEL_FLOW);
112 public void update(InstanceIdentifier<Interface> key, Interface before, Interface after) {
113 if (before.getType() == null && L2vlan.class.equals(after.getType())) {
118 private boolean isNeutronPort(String name) {
122 } catch (IllegalArgumentException e) {
123 LOG.debug("Port {} is not a Neutron Port, skipping.", name);
129 public void add(InstanceIdentifier<Interface> key, Interface add) {
130 List<String> ofportIds = add.getLowerLayerIf();
132 if (!L2vlan.class.equals(add.getType())) {
136 // When a port is created, we receive multiple notifications.
137 // In ipv6service, we are only interested in the notification for NeutronPort, so we skip other notifications
138 if (ofportIds == null || ofportIds.isEmpty() || !isNeutronPort(add.getName())) {
142 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface;
143 iface = ipv6ServiceUtils.getInterface(add.getName());
145 LOG.debug("Port {} is a Neutron port", iface.getName());
146 NodeConnectorId nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
147 Uint64 dpId = Ipv6ServiceUtils.getDpnIdFromNodeConnectorId(nodeConnectorId);
149 if (!dpId.equals(Ipv6ServiceConstants.INVALID_DPID)) {
150 Uuid portId = new Uuid(iface.getName());
151 VirtualPort port = ifMgr.obtainV6Interface(portId);
153 LOG.info("Port {} does not include IPv6Address, skipping.", portId);
157 Long ofPort = MDSALUtil.getOfPortNumberFromPortName(nodeConnectorId);
158 ifMgr.updateDpnInfo(portId, dpId, ofPort);
160 if (!ipv6ServiceEosHandler.isClusterOwner()) {
161 LOG.trace("Not a cluster Owner, skipping further IPv6 processing on this node.");
165 VirtualPort routerPort = ifMgr.getRouterV6InterfaceForNetwork(port.getNetworkID());
166 if (routerPort == null) {
167 LOG.info("Port {} is not associated to a Router, skipping.", portId);
170 ifMgr.handleInterfaceStateEvent(port, dpId, routerPort, Ipv6ServiceConstants.ADD_FLOW);
172 if (!port.getServiceBindingStatus()) {
173 jobCoordinator.enqueueJob("IPv6-" + String.valueOf(portId), () -> {
175 Long elanTag = ifMgr.getNetworkElanTag(routerPort.getNetworkID());
176 ipv6ServiceUtils.bindIpv6Service(portId.getValue(), elanTag, NwConstants.IPV6_TABLE);
177 port.setServiceBindingStatus(true);
178 return Collections.emptyList();
179 }, SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());