fc42da86b5e2a0d0d4ccc68e24ea2da427a111dc
[netvirt.git] / vpnservice / ipv6service / impl / src / main / java / org / opendaylight / netvirt / ipv6service / Ipv6ServiceInterfaceEventListener.java
1 /*
2  * Copyright (c) 2016 Red Hat, Inc. and others. All rights reserved.
3  *
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
7  */
8 package org.opendaylight.netvirt.ipv6service;
9
10 import java.math.BigInteger;
11 import java.util.List;
12 import org.apache.commons.lang3.tuple.ImmutablePair;
13 import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
14 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
15 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
16 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
17 import org.opendaylight.genius.mdsalutil.MDSALUtil;
18 import org.opendaylight.genius.mdsalutil.NwConstants;
19 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
20 import org.opendaylight.netvirt.ipv6service.utils.Ipv6Constants;
21 import org.opendaylight.netvirt.ipv6service.utils.Ipv6ServiceUtils;
22 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.Tunnel;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
26 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
28 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 public class Ipv6ServiceInterfaceEventListener
33         extends AsyncDataTreeChangeListenerBase<Interface, Ipv6ServiceInterfaceEventListener>
34         implements ClusteredDataTreeChangeListener<Interface>, AutoCloseable {
35     private static final Logger LOG = LoggerFactory.getLogger(Ipv6ServiceInterfaceEventListener.class);
36     private final DataBroker dataBroker;
37     private final IMdsalApiManager mdsalUtil;
38     private final IfMgr ifMgr;
39     private Ipv6ServiceUtils ipv6ServiceUtils;
40
41     /**
42      * Intialize the member variables.
43      * @param broker the data broker instance.
44      */
45     public Ipv6ServiceInterfaceEventListener(DataBroker broker, IMdsalApiManager mdsalUtil) {
46         super(Interface.class, Ipv6ServiceInterfaceEventListener.class);
47         this.dataBroker = broker;
48         this.mdsalUtil = mdsalUtil;
49         ifMgr = IfMgr.getIfMgrInstance();
50         ipv6ServiceUtils = new Ipv6ServiceUtils();
51     }
52
53     public void start() {
54         LOG.info("{} start", getClass().getSimpleName());
55         registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
56     }
57
58     @Override
59     protected InstanceIdentifier<Interface> getWildCardPath() {
60         return InstanceIdentifier.create(InterfacesState.class).child(Interface.class);
61     }
62
63     @Override
64     protected void remove(InstanceIdentifier<Interface> key, Interface del) {
65         LOG.debug("Port removed {}, {}", key, del);
66         List<String> ofportIds = del.getLowerLayerIf();
67         if (ofportIds == null || ofportIds.isEmpty()) {
68             return;
69         }
70         String interfaceName = del.getName();
71         ImmutablePair<String, VirtualPort> pair = ifMgr.getInterfaceCache(interfaceName);
72         if (pair != null && pair.getLeft() != null && pair.getRight() != null) {
73             NodeConnectorId nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
74             BigInteger dpId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId));
75             if (!dpId.equals(Ipv6Constants.INVALID_DPID)) {
76                 VirtualPort routerPort = pair.getRight();
77                 ipv6ServiceUtils.unbindIpv6Service(dataBroker, interfaceName);
78                 ipv6ServiceUtils.installIcmpv6RsPuntFlow(NwConstants.IPV6_TABLE, dpId, pair.getLeft(),
79                         mdsalUtil, Ipv6Constants.DEL_FLOW);
80                 for (Ipv6Address ipv6Address : routerPort.getIpv6Addresses()) {
81                     ipv6ServiceUtils.installIcmpv6NsPuntFlow(NwConstants.IPV6_TABLE, dpId,
82                             pair.getLeft(), ipv6Address.getValue(), mdsalUtil, Ipv6Constants.DEL_FLOW);
83                 }
84                 ifMgr.removeInterfaceCache(interfaceName);
85                 ifMgr.deleteInterface(new Uuid(del.getName()), dpId.toString());
86             }
87         }
88     }
89
90     @Override
91     protected void update(InstanceIdentifier<Interface> key, Interface dataObjectModificationBefore,
92                           Interface dataObjectModificationAfter) {
93         // TODO Auto-generated method stub
94         LOG.debug("Port updated...");
95     }
96
97     @Override
98     protected void add(InstanceIdentifier<Interface> key, Interface add) {
99         LOG.debug("Port added {}, {}", key, add);
100         List<String> ofportIds = add.getLowerLayerIf();
101         // When a port is created, we receive two notifications.
102         // 1. where the interface name is dpnid:tapinterfaceName (f.e., 238412509713739:tapf662f5bf-9d)
103         // 2. neutron interface with name as UUID (f.e., f662f5bf-9d54-4dd7-8bcd-7a0a3a0bae4a)
104         // In ipv6service, we are interested only in notification-2, so we skip notification-1.
105         if (ofportIds == null || ofportIds.isEmpty() || add.getName().contains(":")) {
106             return;
107         }
108
109         if (add.getType() != null && add.getType().equals(Tunnel.class)) {
110             LOG.info("iface {} is a tunnel interface, skipping.", add);
111             return;
112         }
113
114         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface;
115         iface = Ipv6ServiceUtils.getInterface(dataBroker, add.getName());
116         if (null != iface) {
117             LOG.debug("Port added {}", iface);
118             NodeConnectorId nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
119             BigInteger dpId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId));
120
121             if (!dpId.equals(Ipv6Constants.INVALID_DPID)) {
122                 Uuid portId = new Uuid(iface.getName());
123                 VirtualPort port = ifMgr.obtainV6Interface(portId);
124                 if (port == null) {
125                     LOG.info("Port {} not found, skipping.", port);
126                     return;
127                 }
128
129                 Long ofPort = MDSALUtil.getOfPortNumberFromPortName(nodeConnectorId);
130                 ifMgr.updateInterface(portId, dpId.toString(), ofPort);
131
132                 VirtualPort routerPort = ifMgr.getRouterV6InterfaceForNetwork(port.getNetworkID());
133                 if (routerPort == null) {
134                     LOG.info("Port {} is not associated to a Router, skipping.", routerPort);
135                     return;
136                 }
137
138                 ipv6ServiceUtils.installIcmpv6RsPuntFlow(NwConstants.IPV6_TABLE, dpId,
139                         port.getMacAddress(), mdsalUtil, Ipv6Constants.ADD_FLOW);
140                 for (Ipv6Address ipv6Address : routerPort.getIpv6Addresses()) {
141                     ipv6ServiceUtils.installIcmpv6NsPuntFlow(NwConstants.IPV6_TABLE, dpId,
142                             port.getMacAddress(), ipv6Address.getValue(), mdsalUtil, Ipv6Constants.ADD_FLOW);
143                 }
144                 ipv6ServiceUtils.bindIpv6Service(dataBroker, iface.getName(), NwConstants.IPV6_TABLE);
145                 ifMgr.updateInterfaceCache(iface.getName(), new ImmutablePair<>(port.getMacAddress(), routerPort));
146             }
147         }
148     }
149
150     @Override
151     protected Ipv6ServiceInterfaceEventListener getDataTreeChangeListener() {
152         return Ipv6ServiceInterfaceEventListener.this;
153     }
154 }