2 * Copyright (c) 2015 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.vpnservice.dhcpservice;
10 import org.opendaylight.vpnservice.neutronvpn.interfaces.INeutronVpnManager;
11 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetKey;
12 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
14 import com.google.common.base.Optional;
16 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
17 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
18 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
19 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
21 import java.math.BigInteger;
22 import java.util.ArrayList;
23 import java.util.List;
25 import com.google.common.util.concurrent.FutureCallback;
27 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
28 import org.opendaylight.vpnservice.dhcpservice.api.DHCPMConstants;
29 import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
30 import org.opendaylight.vpnservice.mdsalutil.ActionType;
31 import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
32 import org.opendaylight.vpnservice.mdsalutil.InstructionInfo;
33 import org.opendaylight.vpnservice.mdsalutil.InstructionType;
34 import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
35 import org.opendaylight.vpnservice.mdsalutil.MatchFieldType;
36 import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
37 import org.opendaylight.vpnservice.mdsalutil.NwConstants;
38 import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
39 import org.opendaylight.vpnservice.mdsalutil.packet.IPProtocols;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
45 public class DhcpManager implements AutoCloseable {
47 private static final Logger logger = LoggerFactory.getLogger(DhcpManager.class);
48 private final DataBroker broker;
49 IMdsalApiManager mdsalUtil;
51 private int dhcpOptLeaseTime = 0;
52 private int dhcpOptRenewalTime = 0;
53 private int dhcpOptRebindingTime = 0;
54 private String dhcpOptDefDomainName;
55 private INeutronVpnManager neutronVpnService;
57 private static final FutureCallback<Void> DEFAULT_CALLBACK =
58 new FutureCallback<Void>() {
59 public void onSuccess(Void result) {
60 logger.debug("Success in Datastore write operation");
62 public void onFailure(Throwable error) {
63 logger.error("Error in Datastore write operation", error);
68 * @param db - dataBroker reference
70 public DhcpManager(final DataBroker db) {
72 configureLeaseDuration(DHCPMConstants.DEFAULT_LEASE_TIME);
75 public void setMdsalManager(IMdsalApiManager mdsalManager) {
76 this.mdsalUtil = mdsalManager;
79 public void setNeutronVpnService(INeutronVpnManager neutronVpnService) {
80 logger.debug("Setting NeutronVpn dependency");
81 this.neutronVpnService = neutronVpnService;
85 public void close() throws Exception {
86 logger.info("DHCP Manager Closed");
89 public void installDhcpEntries(BigInteger dpnId) {
90 logger.debug("Installing Default DHCP Flow tp DPN: {}", dpnId);
91 setupDefaultDhcpFlow(dpnId, NwConstants.DHCP_TABLE, NwConstants.ADD_FLOW);
94 private void setupDefaultDhcpFlow(BigInteger dpId, short tableId, int addOrRemove) {
96 List<MatchInfo> matches = new ArrayList<MatchInfo>();
98 matches.add(new MatchInfo(MatchFieldType.eth_type,
99 new long[] { NwConstants.ETHTYPE_IPV4 }));
100 matches.add(new MatchInfo(MatchFieldType.ip_proto,
101 new long[] { IPProtocols.UDP.intValue() }));
102 matches.add(new MatchInfo(MatchFieldType.udp_src,
103 new long[] { DHCPMConstants.dhcpClientPort }));
104 matches.add(new MatchInfo(MatchFieldType.udp_dst,
105 new long[] { DHCPMConstants.dhcpServerPort }));
107 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
108 List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
110 // Punt to controller
111 actionsInfos.add(new ActionInfo(ActionType.punt_to_controller,
113 instructions.add(new InstructionInfo(InstructionType.write_actions,
115 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId,
116 getDefaultDhcpFlowRef(dpId, tableId),DHCPMConstants.DEFAULT_DHCP_FLOW_PRIORITY, "DHCP", 0, 0,
117 DHCPMConstants.COOKIE_DHCP_BASE, matches, instructions);
118 mdsalUtil.installFlow(flowEntity);
121 private String getDefaultDhcpFlowRef(BigInteger dpId, long tableId) {
122 return new StringBuffer().append(DHCPMConstants.FLOWID_PREFIX).append(dpId)
123 .append(NwConstants.FLOWID_SEPARATOR).append(tableId).toString();
126 public int setLeaseDuration(int leaseDuration) {
127 configureLeaseDuration(leaseDuration);
128 return getDhcpLeaseTime();
131 public String setDefaultDomain(String defaultDomain) {
132 this.dhcpOptDefDomainName = defaultDomain;
133 return getDhcpDefDomain();
136 protected int getDhcpLeaseTime() {
137 return this.dhcpOptLeaseTime;
140 protected int getDhcpRenewalTime() {
141 return this.dhcpOptLeaseTime;
144 protected int getDhcpRebindingTime() {
145 return this.dhcpOptLeaseTime;
148 protected String getDhcpDefDomain() {
149 return this.dhcpOptDefDomainName;
152 private void configureLeaseDuration(int leaseTime) {
153 this.dhcpOptLeaseTime = leaseTime;
155 this.dhcpOptRenewalTime = this.dhcpOptLeaseTime/2;
156 this.dhcpOptRebindingTime = (this.dhcpOptLeaseTime*7)/8;
158 this.dhcpOptRenewalTime = -1;
159 this.dhcpOptRebindingTime = -1;
163 public Subnet getNeutronSubnet(Port nPort) {
166 return neutronVpnService.getNeutronSubnet(nPort.getFixedIps().get(0).getSubnetId());
167 } catch (Exception e) {
168 logger.warn("Failed to get Neutron Subnet from Port: {}", e);
174 public Port getNeutronPort(String name) {
176 return neutronVpnService.getNeutronPort(name);
177 } catch (Exception ex) {
178 logger.trace("In getNeutronPort interface name passed {} exception message {}.", name, ex.getMessage());
183 public void installDhcpEntries(BigInteger dpnId, String vmMacAddress) {
184 setupDhcpFlowEntry(dpnId, NwConstants.DHCP_TABLE, vmMacAddress, NwConstants.ADD_FLOW);
187 private void setupDhcpFlowEntry(BigInteger dpId, short tableId, String vmMacAddress, int addOrRemove) {
188 if (dpId == null || dpId == DHCPMConstants.INVALID_DPID || vmMacAddress == null) {
191 List<MatchInfo> matches = new ArrayList<MatchInfo>();
193 matches.add(new MatchInfo(MatchFieldType.eth_type,
194 new long[] { NwConstants.ETHTYPE_IPV4 }));
195 matches.add(new MatchInfo(MatchFieldType.ip_proto,
196 new long[] { IPProtocols.UDP.intValue() }));
197 matches.add(new MatchInfo(MatchFieldType.udp_src,
198 new long[] { DHCPMConstants.dhcpClientPort }));
199 matches.add(new MatchInfo(MatchFieldType.udp_dst,
200 new long[] { DHCPMConstants.dhcpServerPort }));
201 matches.add(new MatchInfo(MatchFieldType.eth_src,
202 new String[] { vmMacAddress }));
204 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
205 List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
207 // Punt to controller
208 actionsInfos.add(new ActionInfo(ActionType.punt_to_controller,
210 instructions.add(new InstructionInfo(InstructionType.write_actions,
212 if (addOrRemove == NwConstants.DEL_FLOW) {
213 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId,
214 getDhcpFlowRef(dpId, tableId, vmMacAddress),
215 DHCPMConstants.DEFAULT_DHCP_FLOW_PRIORITY, "DHCP", 0, 0,
216 DHCPMConstants.COOKIE_DHCP_BASE, matches, null);
217 logger.trace("Removing DHCP Flow DpId {}, vmMacAddress {}", dpId, vmMacAddress);
218 mdsalUtil.removeFlow(flowEntity);
220 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId,
221 getDhcpFlowRef(dpId, tableId, vmMacAddress),DHCPMConstants.DEFAULT_DHCP_FLOW_PRIORITY, "DHCP", 0, 0,
222 DHCPMConstants.COOKIE_DHCP_BASE, matches, instructions);
223 logger.trace("Installing DHCP Flow DpId {}, vmMacAddress {}", dpId, vmMacAddress);
224 mdsalUtil.installFlow(flowEntity);
228 private String getDhcpFlowRef(BigInteger dpId, long tableId, String vmMacAddress) {
229 return new StringBuffer().append(DHCPMConstants.FLOWID_PREFIX)
230 .append(dpId).append(NwConstants.FLOWID_SEPARATOR)
231 .append(tableId).append(NwConstants.FLOWID_SEPARATOR)
232 .append(vmMacAddress).toString();
235 public void unInstallDhcpEntries(BigInteger dpId, String vmMacAddress) {
236 setupDhcpFlowEntry(dpId, NwConstants.DHCP_TABLE, vmMacAddress, NwConstants.DEL_FLOW);
239 public void setupTableMissForDhcpTable(BigInteger dpId) {
240 List<MatchInfo> matches = new ArrayList<MatchInfo>();
241 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
242 instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NwConstants.LPORT_DISPATCHER_TABLE }));
244 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.DHCP_TABLE, "DHCPTableMissFlow",
245 0, "DHCP Table Miss Flow", 0, 0,
246 DHCPMConstants.COOKIE_DHCP_BASE, matches, instructions);
247 mdsalUtil.installFlow(flowEntity);