458ad968210da082b0d554468a3e3b7878dd983e
[vpnservice.git] / dhcpservice / dhcpservice-impl / src / main / java / org / opendaylight / vpnservice / dhcpservice / DhcpManager.java
1 /*
2  * Copyright (c) 2015 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.dhcpservice;
9
10 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetKey;
11
12 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
13 import com.google.common.base.Optional;
14 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
15 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
16 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
17 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
18 import java.math.BigInteger;
19 import java.util.ArrayList;
20 import java.util.List;
21 import com.google.common.util.concurrent.FutureCallback;
22 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
23 import org.opendaylight.vpnservice.dhcpservice.api.DHCPMConstants;
24 import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
25 import org.opendaylight.vpnservice.mdsalutil.ActionType;
26 import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
27 import org.opendaylight.vpnservice.mdsalutil.InstructionInfo;
28 import org.opendaylight.vpnservice.mdsalutil.InstructionType;
29 import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
30 import org.opendaylight.vpnservice.mdsalutil.MatchFieldType;
31 import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
32 import org.opendaylight.vpnservice.mdsalutil.NwConstants;
33 import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
34 import org.opendaylight.vpnservice.mdsalutil.packet.IPProtocols;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40 public class DhcpManager implements AutoCloseable {
41
42     private static final Logger logger = LoggerFactory.getLogger(DhcpManager.class);
43     private final DataBroker broker;
44     IMdsalApiManager mdsalUtil;
45
46     private int dhcpOptLeaseTime = 0;
47     private int dhcpOptRenewalTime = 0;
48     private int dhcpOptRebindingTime = 0;
49     private String dhcpOptDefDomainName = "openstacklocal";
50
51     private static final FutureCallback<Void> DEFAULT_CALLBACK =
52         new FutureCallback<Void>() {
53             public void onSuccess(Void result) {
54                 logger.debug("Success in Datastore write operation");
55             }
56             public void onFailure(Throwable error) {
57                 logger.error("Error in Datastore write operation", error);
58             };
59         };
60
61     /**
62     * @param db - dataBroker reference
63     */
64     public DhcpManager(final DataBroker db) {
65         broker = db;
66         configureLeaseDuration(DHCPMConstants.DEFAULT_LEASE_TIME);
67     }
68
69     public void setMdsalManager(IMdsalApiManager mdsalManager) {
70         this.mdsalUtil = mdsalManager;
71     }
72
73     @Override
74     public void close() throws Exception {
75         logger.info("DHCP Manager Closed");
76     }
77
78     public void installDhcpEntries(BigInteger dpnId) {
79         logger.debug("Installing Default DHCP Flow tp DPN: {}", dpnId);
80         setupDefaultDhcpFlow(dpnId, DHCPMConstants.DHCP_TABLE, NwConstants.ADD_FLOW);
81     }
82
83     private void setupDefaultDhcpFlow(BigInteger dpId,  short tableId, int addOrRemove) {
84
85         List<MatchInfo> matches = new ArrayList<MatchInfo>();
86
87         matches.add(new MatchInfo(MatchFieldType.eth_type,
88                 new long[] { NwConstants.ETHTYPE_IPV4 }));
89         matches.add(new MatchInfo(MatchFieldType.ip_proto,
90                 new long[] { IPProtocols.UDP.intValue() }));
91         matches.add(new MatchInfo(MatchFieldType.udp_src,
92                 new long[] { DHCPMConstants.dhcpClientPort }));
93         matches.add(new MatchInfo(MatchFieldType.udp_dst,
94                 new long[] { DHCPMConstants.dhcpServerPort }));
95
96         List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
97         List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
98
99         // Punt to controller
100         actionsInfos.add(new ActionInfo(ActionType.punt_to_controller,
101                 new String[] {}));
102         instructions.add(new InstructionInfo(InstructionType.write_actions,
103                 actionsInfos));
104         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId,
105                 getDefaultDhcpFlowRef(dpId, tableId),DHCPMConstants.DEFAULT_DHCP_FLOW_PRIORITY, "DHCP", 0, 0,
106                 DHCPMConstants.COOKIE_DHCP_BASE, matches, instructions);
107         mdsalUtil.installFlow(flowEntity);
108     }
109
110     private String getDefaultDhcpFlowRef(BigInteger dpId, long tableId) {
111         return new StringBuffer().append(DHCPMConstants.FLOWID_PREFIX).append(dpId)
112                         .append(NwConstants.FLOWID_SEPARATOR).append(tableId).toString();
113     }
114
115     public int setLeaseDuration(int leaseDuration) {
116         configureLeaseDuration(leaseDuration);
117         return getDhcpLeaseTime();
118     }
119
120     public String setDefaultDomain(String defaultDomain) {
121         this.dhcpOptDefDomainName = defaultDomain;
122         return getDhcpDefDomain();
123     }
124
125     protected int getDhcpLeaseTime() {
126         return this.dhcpOptLeaseTime;
127     }
128
129     protected int getDhcpRenewalTime() {
130         return this.dhcpOptLeaseTime;
131     }
132
133     protected int getDhcpRebindingTime() {
134         return this.dhcpOptLeaseTime;
135     }
136
137     protected String getDhcpDefDomain() {
138         return this.dhcpOptDefDomainName;
139     }
140
141     private void configureLeaseDuration(int leaseTime) {
142         this.dhcpOptLeaseTime = leaseTime;
143         if(leaseTime > 0) {
144             this.dhcpOptRenewalTime = this.dhcpOptLeaseTime/2;
145             this.dhcpOptRebindingTime = (this.dhcpOptLeaseTime*7)/8;
146         } else {
147             this.dhcpOptRenewalTime = -1;
148             this.dhcpOptRebindingTime = -1;
149         }
150     }
151
152     public Subnet getNeutronSubnet(Port nPort) {
153         /* TODO: Once NeutronVpn is merged, use it to get Subnet
154         if (nPort != null) {
155             try {
156                 return neutronVpnService.getNeutronSubnet(nPort.getFixedIps().get(0).getSubnetId());
157             } catch (Exception e) {
158                 logger.warn("Failed to get Neutron Subnet from Port: {}", e);
159             }
160         }
161         */
162         if (nPort.getFixedIps() != null && !nPort.getFixedIps().isEmpty()) {
163             InstanceIdentifier<Subnet> sIid =
164                             InstanceIdentifier.create(Neutron.class).child(Subnets.class)
165                                 .child(Subnet.class, new SubnetKey(nPort.getFixedIps().get(0).getSubnetId()));
166             Optional<Subnet> optSubnet = MDSALUtil.read(LogicalDatastoreType.CONFIGURATION, sIid, broker);
167             if (optSubnet.isPresent()) {
168                 return optSubnet.get();
169             }
170         }
171         return null;
172     }
173
174     public Port getNeutronPort(String name) {
175         // TODO Once NeutronVpn is merged, use it to get port
176         //return neutronVpnService.getNeutronPort(name);
177         InstanceIdentifier<Ports> pIid = InstanceIdentifier.create(Neutron.class).child(Ports.class);
178         Optional<Ports> optPorts = MDSALUtil.read(LogicalDatastoreType.CONFIGURATION, pIid, broker);
179         if(optPorts.isPresent()) {
180             for(Port port: optPorts.get().getPort()) {
181                 if(port.getUuid().getValue().startsWith(name.substring(3))) {
182                     return port;
183                 }
184             }
185         }
186         return null;
187     }
188
189 }