Using Table Ids from NwConstants.java
[netvirt.git] / vpnservice / natservice / natservice-impl / src / main / java / org / opendaylight / netvirt / natservice / internal / NaptPacketInHandler.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 package org.opendaylight.netvirt.natservice.internal;
9
10 import org.opendaylight.controller.liblldp.NetUtils;
11 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
12 import org.opendaylight.genius.mdsalutil.NwConstants;
13 import org.opendaylight.genius.mdsalutil.packet.Ethernet;
14 import org.opendaylight.genius.mdsalutil.packet.IPv4;
15 import org.opendaylight.genius.mdsalutil.packet.TCP;
16 import org.opendaylight.genius.mdsalutil.packet.UDP;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingListener;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
19 import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory;
21
22 import java.math.BigInteger;
23 import java.util.HashSet;
24 import com.google.common.primitives.Ints;
25
26 public class NaptPacketInHandler implements PacketProcessingListener {
27
28     private static final Logger LOG = LoggerFactory.getLogger(NaptPacketInHandler.class);
29     private final static HashSet<String> incomingPacketMap = new HashSet<>();
30     private final EventDispatcher naptEventdispatcher;
31
32     public NaptPacketInHandler(EventDispatcher eventDispatcher) {
33         this.naptEventdispatcher = eventDispatcher;
34     }
35
36     @Override
37     public void onPacketReceived(PacketReceived packetReceived) {
38         String internalIPAddress = "";
39         int portNumber = 0;
40         long routerId = 0L;
41         NAPTEntryEvent.Operation operation = NAPTEntryEvent.Operation.ADD;
42         NAPTEntryEvent.Protocol protocol;
43
44         Short tableId = packetReceived.getTableId().getValue();
45
46         if (LOG.isTraceEnabled()) {
47             LOG.trace("packet: {}, tableId {}", packetReceived, tableId);
48         }
49
50         if (tableId == NwConstants.OUTBOUND_NAPT_TABLE) {
51             LOG.debug("NAT Service : NAPTPacketInHandler Packet for Outbound NAPT Table");
52             byte[] inPayload = packetReceived.getPayload();
53             Ethernet ethPkt = new Ethernet();
54             if (inPayload != null) {
55                 try {
56                     ethPkt.deserialize(inPayload, 0, inPayload.length * NetUtils.NumBitsInAByte);
57                 } catch (Exception e) {
58                     LOG.warn("Failed to decode Packet", e);
59                     return;
60                 }
61                 if (ethPkt.getPayload() instanceof IPv4) {
62                     IPv4 ipPkt = (IPv4) ethPkt.getPayload();
63                     byte[] ipSrc = Ints.toByteArray(ipPkt.getSourceAddress());
64
65                     internalIPAddress = NatUtil.toStringIpAddress(ipSrc, LOG);
66                     LOG.trace("Retrieved internalIPAddress {}", internalIPAddress);
67                     if (ipPkt.getPayload() instanceof TCP) {
68                         TCP tcpPkt = (TCP) ipPkt.getPayload();
69                         portNumber = tcpPkt.getSourcePort();
70                         if(portNumber < 0){
71                             portNumber = 32767 + portNumber + 32767 + 2;
72                             LOG.trace("Retrieved and extracted TCP portNumber {}", portNumber);
73                         }
74                         protocol = NAPTEntryEvent.Protocol.TCP;
75                         LOG.trace("Retrieved TCP portNumber {}", portNumber);
76                     } else if (ipPkt.getPayload() instanceof UDP) {
77                         UDP udpPkt = (UDP) ipPkt.getPayload();
78                         portNumber = udpPkt.getSourcePort();
79                         if(portNumber < 0){
80                             portNumber = 32767 + portNumber + 32767 + 2;
81                             LOG.trace("Retrieved and extracted UDP portNumber {}", portNumber);
82                         }
83                         protocol = NAPTEntryEvent.Protocol.UDP;
84                         LOG.trace("Retrieved UDP portNumber {}", portNumber);
85                     } else {
86                         LOG.error("Incoming Packet is neither TCP or UDP packet");
87                         return;
88                     }
89                 } else {
90                     LOG.error("Incoming Packet is not IPv4 packet");
91                     return;
92                 }
93
94                 if(internalIPAddress != null) {
95                     String sourceIPPortKey = internalIPAddress + ":" + portNumber;
96                     LOG.debug("NAT Service : sourceIPPortKey {} mapping maintained in the map", sourceIPPortKey);
97                     if (!incomingPacketMap.contains(sourceIPPortKey)) {
98                         incomingPacketMap.add(internalIPAddress + portNumber);
99                         LOG.trace("NAT Service : Processing new Packet");
100                         BigInteger metadata = packetReceived.getMatch().getMetadata().getMetadata();
101                         routerId = (metadata.and(MetaDataUtil.METADATA_MASK_VRFID)).longValue();
102                         if( routerId <= 0) {
103                             LOG.error("NAT Service : Router ID is invalid");
104                             return;
105                         }
106                         //send to Event Queue
107                         LOG.trace("NAT Service : Creating NaptEvent for routerId {} and sourceIp {} and Port {}", routerId,
108                                 internalIPAddress, portNumber);
109                         NAPTEntryEvent naptEntryEvent = new NAPTEntryEvent(internalIPAddress,portNumber,routerId,
110                                 operation,protocol, packetReceived, false);
111                         naptEventdispatcher.addNaptEvent(naptEntryEvent);
112                         LOG.trace("NAT Service : PacketInHandler sent event to NaptEventHandler");
113                     } else {
114                         LOG.trace("NAT Service : Packet already processed");
115                         NAPTEntryEvent naptEntryEvent = new NAPTEntryEvent(internalIPAddress,portNumber,routerId,
116                                 operation,protocol, packetReceived, true);
117                         LOG.trace("NAT Service : PacketInHandler sent event to NaptEventHandler");
118                     }
119                 }else {
120                     LOG.error("Nullpointer exception in retrieving internalIPAddress");
121                 }
122             }
123         }else {
124             LOG.trace("Packet is not from the Outbound NAPT table");
125         }
126     }
127
128     public void removeIncomingPacketMap(String sourceIPPortKey) {
129         incomingPacketMap.remove(sourceIPPortKey);
130         LOG.debug("NAT Service : sourceIPPortKey {} mapping is removed from map", sourceIPPortKey);
131     }
132 }