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