2 * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. 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.natservice.internal;
10 import java.math.BigInteger;
11 import javax.inject.Inject;
12 import javax.inject.Singleton;
13 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
14 import org.opendaylight.genius.mdsalutil.FlowEntity;
15 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
16 import org.opendaylight.genius.mdsalutil.NwConstants;
17 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
18 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAdded;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowUpdated;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeErrorNotification;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeExperimenterErrorNotification;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowListener;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SwitchFlowRemoved;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.RemovedFlowReason;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.TcpMatchFields;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.UdpMatchFields;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer4Match;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.TcpMatch;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._4.match.UdpMatch;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.intext.ip.port.map.ip.port.mapping.intext.ip.protocol.type.ip.port.map.IpPortExternal;
36 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
41 public class NaptFlowRemovedEventHandler implements SalFlowListener {
42 private static final Logger LOG = LoggerFactory.getLogger(NaptFlowRemovedEventHandler.class);
43 private final DataBroker dataBroker;
44 private final IMdsalApiManager mdsalManager;
45 private final EventDispatcher naptEventdispatcher;
46 private final NaptPacketInHandler naptPacketInHandler;
47 private final NaptManager naptManager;
50 public NaptFlowRemovedEventHandler(final DataBroker dataBroker,
51 final IMdsalApiManager mdsalManager,
52 final EventDispatcher eventDispatcher,
53 final NaptPacketInHandler handler,
54 final NaptManager naptManager) {
55 this.dataBroker = dataBroker;
56 this.mdsalManager = mdsalManager;
57 this.naptEventdispatcher = eventDispatcher;
58 this.naptPacketInHandler = handler;
59 this.naptManager = naptManager;
63 public void onSwitchFlowRemoved(SwitchFlowRemoved flowRemoved) {
67 private BigInteger getDpnId(String node) {
69 String[] temp = node.split(":");
70 return new BigInteger(temp[1]);
75 public void onFlowAdded(FlowAdded arg0) {
76 // TODO Auto-generated method stub
81 public void onFlowRemoved(FlowRemoved flowRemoved) {
83 If the removed flow is from the OUTBOUND NAPT table :
84 1) Get the ActionInfo of the flow.
85 2) From the ActionInfo of the flow get the internal IP address, port and the protocol.
86 3) Get the Metadata matching info of the flow.
87 4) From the Metadata matching info of the flow get router ID.
88 5) Querry the container intext-ip-port-map using the router ID
89 and the internal IP address, port to get the external IP address, port
90 6) Instantiate an NaptEntry event and populate the external IP address, port and the router ID.
91 7) Place the NaptEntry event to the queue.
94 short tableId = flowRemoved.getTableId();
95 RemovedFlowReason removedReasonFlag = flowRemoved.getReason();
96 if (tableId == NwConstants.OUTBOUND_NAPT_TABLE
97 && RemovedFlowReason.OFPRRIDLETIMEOUT.equals(removedReasonFlag)) {
98 LOG.info("onFlowRemoved : triggered for table-{} entry", tableId);
100 //Get the internal internal IP address and the port number from the IPv4 match.
101 Ipv4Prefix internalIpv4Address = null;
102 Layer3Match layer3Match = flowRemoved.getMatch().getLayer3Match();
103 if (layer3Match instanceof Ipv4Match) {
104 Ipv4Match internalIpv4Match = (Ipv4Match) layer3Match;
105 internalIpv4Address = internalIpv4Match.getIpv4Source();
107 if (internalIpv4Address == null) {
108 LOG.error("onFlowRemoved : Matching internal IP is null while retrieving the "
109 + "value from the Outbound NAPT flow");
112 //Get the internal IP as a string
113 String internalIpv4AddressAsString = internalIpv4Address.getValue();
114 String[] internalIpv4AddressParts = internalIpv4AddressAsString.split("/");
115 String internalIpv4HostAddress = null;
116 if (internalIpv4AddressParts.length >= 1) {
117 internalIpv4HostAddress = internalIpv4AddressParts[0];
120 //Get the protocol from the layer4 match
121 NAPTEntryEvent.Protocol protocol = null;
122 Integer internalPortNumber = null;
123 Layer4Match layer4Match = flowRemoved.getMatch().getLayer4Match();
124 if (layer4Match instanceof TcpMatch) {
125 TcpMatchFields tcpMatchFields = (TcpMatchFields) layer4Match;
126 internalPortNumber = tcpMatchFields.getTcpSourcePort().getValue();
127 protocol = NAPTEntryEvent.Protocol.TCP;
128 } else if (layer4Match instanceof UdpMatch) {
129 UdpMatchFields udpMatchFields = (UdpMatchFields) layer4Match;
130 internalPortNumber = udpMatchFields.getUdpSourcePort().getValue();
131 protocol = NAPTEntryEvent.Protocol.UDP;
133 if (protocol == null) {
134 LOG.error("onFlowRemoved : Matching protocol is null while retrieving the value "
135 + "from the Outbound NAPT flow");
139 //Get the router ID from the metadata.
141 BigInteger metadata = flowRemoved.getMatch().getMetadata().getMetadata();
142 if (MetaDataUtil.getNatRouterIdFromMetadata(metadata) != 0) {
143 routerId = MetaDataUtil.getNatRouterIdFromMetadata(metadata);
145 LOG.error("onFlowRemoved : Null exception while retrieving routerId");
148 final String internalIpPortKey = routerId + NatConstants.COLON_SEPARATOR
149 + internalIpv4HostAddress + NatConstants.COLON_SEPARATOR + internalPortNumber;
150 //Get the external IP address and the port from the model
151 IpPortExternal ipPortExternal = NatUtil.getExternalIpPortMap(dataBroker, routerId,
152 internalIpv4HostAddress, internalPortNumber.toString(), protocol);
153 if (ipPortExternal == null) {
154 LOG.error("onFlowRemoved : IpPortExternal not found, BGP vpn might be "
155 + "associated with router");
156 //router must be associated with BGP vpn ID
157 long bgpVpnId = routerId;
158 LOG.debug("onFlowRemoved : BGP VPN ID {}", bgpVpnId);
159 String vpnName = NatUtil.getRouterName(dataBroker, bgpVpnId);
160 String routerName = NatUtil.getRouterIdfromVpnInstance(dataBroker, vpnName);
161 if (routerName == null) {
162 LOG.error("onFlowRemoved : Unable to find router for VpnName {}", vpnName);
165 routerId = NatUtil.getVpnId(dataBroker, routerName);
166 LOG.debug("onFlowRemoved : Router ID {}", routerId);
167 ipPortExternal = NatUtil.getExternalIpPortMap(dataBroker, routerId,
168 internalIpv4HostAddress, internalPortNumber.toString(), protocol);
169 if (ipPortExternal == null) {
170 LOG.error("onFlowRemoved : IpPortExternal is null while queried from the "
171 + "model for routerId {}", routerId);
175 String externalIpAddress = ipPortExternal.getIpAddress();
176 int externalPortNumber = ipPortExternal.getPortNum();
178 //Create an NAPT event and place it in the queue.
179 NAPTEntryEvent naptEntryEvent = new NAPTEntryEvent(externalIpAddress, externalPortNumber,
180 routerId, NAPTEntryEvent.Operation.DELETE, protocol, null, false);
181 naptEventdispatcher.addFlowRemovedNaptEvent(naptEntryEvent);
183 //Get the DPN ID from the Node
184 InstanceIdentifier<Node> nodeRef = flowRemoved.getNode().getValue().firstIdentifierOf(Node.class);
185 String dpn = nodeRef.firstKeyOf(Node.class).getId().getValue();
186 BigInteger dpnId = getDpnId(dpn);
187 String switchFlowRef = NatUtil.getNaptFlowRef(dpnId, tableId, String.valueOf(routerId),
188 internalIpv4HostAddress, internalPortNumber);
190 //Inform the MDSAL manager to inform about the flow removal.
191 LOG.debug("onFlowRemoved : DPN ID {}, Metadata {}, SwitchFlowRef {}, "
192 + "internalIpv4HostAddress{}", dpnId, routerId, switchFlowRef, internalIpv4AddressAsString);
193 FlowEntity snatFlowEntity = NatUtil.buildFlowEntity(dpnId, tableId, switchFlowRef);
194 long startTime = System.currentTimeMillis();
195 mdsalManager.removeFlow(snatFlowEntity);
196 LOG.debug("onFlowRemoved : Elapsed time fo deleting table-{} flow for snat ({}) session:{}ms",
197 tableId, internalIpPortKey, (System.currentTimeMillis() - startTime));
198 //Remove the SourceIP:Port key from the Napt packet handler map.
199 naptPacketInHandler.removeIncomingPacketMap(internalIpPortKey);
201 //Remove the mapping of internal fixed ip/port to external ip/port from the datastore.
202 SessionAddress internalSessionAddress = new SessionAddress(internalIpv4HostAddress, internalPortNumber);
203 naptManager.releaseIpExtPortMapping(routerId, internalSessionAddress, protocol);
204 LOG.info("onFlowRemoved : exit");
206 LOG.debug("onFlowRemoved : Received flow removed notification due to flowdelete from switch for flowref");
212 public void onFlowUpdated(FlowUpdated arg0) {
213 // TODO Auto-generated method stub
218 public void onNodeErrorNotification(NodeErrorNotification arg0) {
219 // TODO Auto-generated method stub
224 public void onNodeExperimenterErrorNotification(NodeExperimenterErrorNotification arg0) {
225 // TODO Auto-generated method stub