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.PostConstruct;
13 import javax.inject.Inject;
14 import javax.inject.Singleton;
15 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
16 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
17 import org.opendaylight.genius.datastoreutils.AsyncClusteredDataTreeChangeListenerBase;
18 import org.opendaylight.genius.mdsalutil.MDSALUtil;
19 import org.opendaylight.genius.mdsalutil.NwConstants;
20 import org.opendaylight.genius.utils.SystemPropertyReader;
21 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
22 import org.opendaylight.netvirt.ipv6service.utils.Ipv6ServiceConstants;
23 import org.opendaylight.netvirt.ipv6service.utils.Ipv6ServiceUtils;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev170119.L2vlan;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
27 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
29 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
30 import org.opendaylight.yangtools.yang.common.Uint64;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
35 public class Ipv6ServiceInterfaceEventListener
36 extends AsyncClusteredDataTreeChangeListenerBase<Interface, Ipv6ServiceInterfaceEventListener> {
37 private static final Logger LOG = LoggerFactory.getLogger(Ipv6ServiceInterfaceEventListener.class);
38 private final DataBroker dataBroker;
39 private final IfMgr ifMgr;
40 private final Ipv6ServiceUtils ipv6ServiceUtils;
41 private final JobCoordinator jobCoordinator;
42 private final Ipv6ServiceEosHandler ipv6ServiceEosHandler;
45 * Intialize the member variables.
46 * @param broker the data broker instance.
49 public Ipv6ServiceInterfaceEventListener(DataBroker broker, IfMgr ifMgr, Ipv6ServiceUtils ipv6ServiceUtils,
50 final JobCoordinator jobCoordinator, Ipv6ServiceEosHandler ipv6ServiceEosHandler) {
51 super(Interface.class, Ipv6ServiceInterfaceEventListener.class);
52 this.dataBroker = broker;
54 this.ipv6ServiceUtils = ipv6ServiceUtils;
55 this.jobCoordinator = jobCoordinator;
56 this.ipv6ServiceEosHandler = ipv6ServiceEosHandler;
61 LOG.info("{} init", getClass().getSimpleName());
62 registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
66 protected InstanceIdentifier<Interface> getWildCardPath() {
67 return InstanceIdentifier.create(InterfacesState.class).child(Interface.class);
71 protected void remove(InstanceIdentifier<Interface> key, Interface del) {
72 LOG.debug("Port removed {}, {}", key, del);
73 if (!L2vlan.class.equals(del.getType())) {
77 // In ipv6service, we are only interested in the notification for NeutronPort, so we skip other notifications
78 List<String> ofportIds = del.getLowerLayerIf();
79 if (ofportIds == null || ofportIds.isEmpty() || !isNeutronPort(del.getName())) {
83 if (!ipv6ServiceEosHandler.isClusterOwner()) {
84 LOG.trace("Not a cluster Owner, skipping further IPv6 processing on this node.");
87 Uuid portId = new Uuid(del.getName());
88 VirtualPort port = ifMgr.obtainV6Interface(portId);
90 LOG.info("Port {} does not include IPv6Address, skipping.", portId);
94 if (port.getServiceBindingStatus()) {
95 jobCoordinator.enqueueJob("IPv6-" + String.valueOf(portId), () -> {
97 ipv6ServiceUtils.unbindIpv6Service(portId.getValue());
98 port.setServiceBindingStatus(false);
99 return Collections.emptyList();
100 }, SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
103 VirtualPort routerPort = ifMgr.getRouterV6InterfaceForNetwork(port.getNetworkID());
104 ifMgr.handleInterfaceStateEvent(port, ipv6ServiceUtils.getDpIdFromInterfaceState(del), routerPort,
105 Ipv6ServiceConstants.DEL_FLOW);
109 protected void update(InstanceIdentifier<Interface> key, Interface before, Interface after) {
110 if (before.getType() == null && L2vlan.class.equals(after.getType())) {
115 private boolean isNeutronPort(String name) {
119 } catch (IllegalArgumentException e) {
120 LOG.debug("Port {} is not a Neutron Port, skipping.", name);
126 protected void add(InstanceIdentifier<Interface> key, Interface add) {
127 List<String> ofportIds = add.getLowerLayerIf();
129 if (!L2vlan.class.equals(add.getType())) {
133 // When a port is created, we receive multiple notifications.
134 // In ipv6service, we are only interested in the notification for NeutronPort, so we skip other notifications
135 if (ofportIds == null || ofportIds.isEmpty() || !isNeutronPort(add.getName())) {
139 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface;
140 iface = ipv6ServiceUtils.getInterface(add.getName());
142 LOG.debug("Port {} is a Neutron port", iface.getName());
143 NodeConnectorId nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
144 Uint64 dpId = Ipv6ServiceUtils.getDpnIdFromNodeConnectorId(nodeConnectorId);
146 if (!dpId.equals(Ipv6ServiceConstants.INVALID_DPID)) {
147 Uuid portId = new Uuid(iface.getName());
148 VirtualPort port = ifMgr.obtainV6Interface(portId);
150 LOG.info("Port {} does not include IPv6Address, skipping.", portId);
154 Long ofPort = MDSALUtil.getOfPortNumberFromPortName(nodeConnectorId);
155 ifMgr.updateDpnInfo(portId, dpId, ofPort);
157 if (!ipv6ServiceEosHandler.isClusterOwner()) {
158 LOG.trace("Not a cluster Owner, skipping further IPv6 processing on this node.");
162 VirtualPort routerPort = ifMgr.getRouterV6InterfaceForNetwork(port.getNetworkID());
163 if (routerPort == null) {
164 LOG.info("Port {} is not associated to a Router, skipping.", portId);
167 ifMgr.handleInterfaceStateEvent(port, dpId, routerPort, Ipv6ServiceConstants.ADD_FLOW);
169 if (!port.getServiceBindingStatus()) {
170 jobCoordinator.enqueueJob("IPv6-" + String.valueOf(portId), () -> {
172 Long elanTag = ifMgr.getNetworkElanTag(routerPort.getNetworkID());
173 ipv6ServiceUtils.bindIpv6Service(portId.getValue(), elanTag, NwConstants.IPV6_TABLE);
174 port.setServiceBindingStatus(true);
175 return Collections.emptyList();
176 }, SystemPropertyReader.getDataStoreJobCoordinatorMaxRetries());
183 protected Ipv6ServiceInterfaceEventListener getDataTreeChangeListener() {
184 return Ipv6ServiceInterfaceEventListener.this;