Bump versions by 0.1.0 for next dev cycle
[vpnservice.git] / natservice / natservice-impl / src / main / java / org / opendaylight / vpnservice / natservice / internal / RouterToVpnListener.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.vpnservice.natservice.internal;
9
10 import java.math.BigInteger;
11 import java.util.HashMap;
12 import java.util.List;
13 import java.util.Map;
14 import java.util.concurrent.ExecutionException;
15 import java.util.concurrent.Future;
16
17 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
18 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
19 import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
20 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetDpidFromInterfaceInput;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetDpidFromInterfaceInputBuilder;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetDpidFromInterfaceOutput;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.RouterPorts;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.Ports;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.floating.ip.info.router.ports.ports.IpMapping;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.IpMappingKey;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.natservice.rev160111.intext.ip.map.ip.mapping.IpMap;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.NeutronvpnListener;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.RouterAssociatedToVpn;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.RouterDisassociatedFromVpn;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.SubnetAddedToVpn;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.SubnetDeletedFromVpn;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.PortAddedToSubnet;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.PortRemovedFromSubnet;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.SubnetUpdatedInVpn;
38 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
39 import org.opendaylight.yangtools.yang.common.RpcResult;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 import com.google.common.base.Optional;
44
45 public class RouterToVpnListener implements NeutronvpnListener {
46     private static final Logger LOG = LoggerFactory.getLogger(RouterToVpnListener.class);
47     private DataBroker dataBroker;
48     private FloatingIPListener floatingIpListener;
49     private OdlInterfaceRpcService interfaceManager;
50
51
52     private ExternalRoutersListener externalRoutersListener;
53
54     public RouterToVpnListener(DataBroker db) {
55         dataBroker = db;
56     }
57
58     void setInterfaceManager(OdlInterfaceRpcService interfaceManager) {
59         this.interfaceManager = interfaceManager;
60     }
61
62     void setFloatingIpListener(FloatingIPListener floatingIpListener) {
63         this.floatingIpListener = floatingIpListener;
64     }
65
66     void setExternalRoutersListener(ExternalRoutersListener externalRoutersListener) {
67         this.externalRoutersListener = externalRoutersListener;
68     }
69
70     /**
71      * router association to vpn
72      *
73      */
74     @Override
75     public void onRouterAssociatedToVpn(RouterAssociatedToVpn notification) {
76         String routerName = notification.getRouterId().getValue();
77         String vpnName = notification.getVpnId().getValue();
78         //check router is associated to external network
79         String extNetwork = NatUtil.getAssociatedExternalNetwork(dataBroker, routerName);
80         if(extNetwork != null) {
81             LOG.debug("Router {} is associated with ext nw {}", routerName, extNetwork);
82             handleDNATConfigurationForRouterAssociation(routerName, vpnName, extNetwork);
83             externalRoutersListener.changeLocalVpnIdToBgpVpnId(routerName, vpnName);
84         } else {
85             LOG.debug("Ignoring the Router {} association with VPN {} since it is not external router", routerName);
86         }
87
88     }
89
90     /**
91      * router disassociation from vpn
92      *
93      */
94     @Override
95     public void onRouterDisassociatedFromVpn(RouterDisassociatedFromVpn notification) {
96         String routerName = notification.getRouterId().getValue();
97         String vpnName = notification.getVpnId().getValue();
98         //check router is associated to external network
99         String extNetwork = NatUtil.getAssociatedExternalNetwork(dataBroker, routerName);
100         if(extNetwork != null) {
101             LOG.debug("Router {} is associated with ext nw {}", routerName, extNetwork);
102             handleDNATConfigurationForRouterDisassociation(routerName, vpnName, extNetwork);
103             externalRoutersListener.changeBgpVpnIdToLocalVpnId(routerName, vpnName);
104         } else {
105             LOG.debug("Ignoring the Router {} association with VPN {} since it is not external router", routerName);
106         }
107     }
108
109     void handleDNATConfigurationForRouterAssociation(String routerName, String vpnName, String externalNetwork) {
110         InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerName);
111         Optional<RouterPorts> optRouterPorts = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerPortsId);
112         if(!optRouterPorts.isPresent()) {
113             LOG.debug("Could not read Router Ports data object with id: {} to handle associate vpn {}", routerName, vpnName);
114             return;
115         }
116         Uuid networkId = Uuid.getDefaultInstance(externalNetwork);
117         RouterPorts routerPorts = optRouterPorts.get();
118         List<Ports> interfaces = routerPorts.getPorts();
119         Map<String, BigInteger> portToDpnMap = new HashMap<>();
120         for(Ports port : interfaces) {
121             String portName = port.getPortName();
122             BigInteger dpnId = getDpnForInterface(interfaceManager, portName);
123             if(dpnId.equals(BigInteger.ZERO)) {
124                 LOG.debug("DPN not found for {}, skip handling of router {} association with vpn", portName, routerName, vpnName);
125                 continue;
126             }
127             portToDpnMap.put(portName, dpnId);
128             List<IpMapping> ipMapping = port.getIpMapping();
129             for(IpMapping ipMap : ipMapping) {
130                 String externalIp = ipMap.getExternalIp();
131                 //remove all NAT related entries with routerName
132                 //floatingIpListener.removeNATOnlyFlowEntries(dpnId, portName, routerName, null, ipMap.getInternalIp(), externalIp);
133                 //Create NAT entries with VPN Id
134                 LOG.debug("Updating DNAT flows with VPN metadata {} ", vpnName);
135                 floatingIpListener.createNATOnlyFlowEntries(dpnId, portName, routerName, vpnName, networkId, ipMap.getInternalIp(), externalIp);
136             }
137         }
138     }
139
140     void handleDNATConfigurationForRouterDisassociation(String routerName, String vpnName, String externalNetwork) {
141         InstanceIdentifier<RouterPorts> routerPortsId = NatUtil.getRouterPortsId(routerName);
142         Optional<RouterPorts> optRouterPorts = MDSALUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, routerPortsId);
143         if(!optRouterPorts.isPresent()) {
144             LOG.debug("Could not read Router Ports data object with id: {} to handle disassociate vpn {}", routerName, vpnName);
145             return;
146         }
147         Uuid networkId = Uuid.getDefaultInstance(externalNetwork);
148         RouterPorts routerPorts = optRouterPorts.get();
149         List<Ports> interfaces = routerPorts.getPorts();
150         for(Ports port : interfaces) {
151             String portName = port.getPortName();
152             BigInteger dpnId = getDpnForInterface(interfaceManager, portName);
153             if(dpnId.equals(BigInteger.ZERO)) {
154                 LOG.debug("DPN not found for {}, skip handling of router {} association with vpn", portName, routerName, vpnName);
155                 continue;
156             }
157             List<IpMapping> ipMapping = port.getIpMapping();
158             for(IpMapping ipMap : ipMapping) {
159                 String externalIp = ipMap.getExternalIp();
160                 //remove all NAT related entries with routerName
161                 //floatingIpListener.removeNATOnlyFlowEntries(dpnId, portName, routerName, vpnName, ipMap.getInternalIp(), externalIp);
162                 //Create NAT entries with VPN Id
163                 floatingIpListener.createNATOnlyFlowEntries(dpnId, portName, routerName, null, networkId, ipMap.getInternalIp(), externalIp);
164             }
165         }
166     }
167
168     private BigInteger getDpnForInterface(OdlInterfaceRpcService interfaceManagerRpcService, String ifName) {
169         BigInteger nodeId = BigInteger.ZERO;
170         try {
171             GetDpidFromInterfaceInput
172                     dpIdInput =
173                     new GetDpidFromInterfaceInputBuilder().setIntfName(ifName).build();
174             Future<RpcResult<GetDpidFromInterfaceOutput>>
175                     dpIdOutput =
176                     interfaceManagerRpcService.getDpidFromInterface(dpIdInput);
177             RpcResult<GetDpidFromInterfaceOutput> dpIdResult = dpIdOutput.get();
178             if (dpIdResult.isSuccessful()) {
179                 nodeId = dpIdResult.getResult().getDpid();
180             } else {
181                 LOG.error("Could not retrieve DPN Id for interface {}", ifName);
182             }
183         } catch (InterruptedException | ExecutionException e) {
184             LOG.error("Exception when getting dpn for interface {}", ifName,  e);
185         }
186         return nodeId;
187     }
188
189     @Override
190     public void onSubnetAddedToVpn(SubnetAddedToVpn notification) {
191         throw new RuntimeException("Unsupported notification");
192     }
193
194     @Override
195     public void onSubnetDeletedFromVpn(SubnetDeletedFromVpn notification) {
196         throw new RuntimeException("Unsupported notification");
197     }
198
199     @Override
200     public void onPortAddedToSubnet(PortAddedToSubnet notification) {
201         throw new RuntimeException("Unsupported notification");
202     }
203
204     @Override
205     public void onPortRemovedFromSubnet(PortRemovedFromSubnet notification) {
206         throw new RuntimeException("Unsupported notification");
207     }
208
209     @Override
210     public void onSubnetUpdatedInVpn(SubnetUpdatedInVpn notification) {
211         throw new RuntimeException("Unsupported notification");
212     }
213
214 }