76d78f6e6b9df0eef1a6a9fe8764fa4a87301878
[netvirt.git] /
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.netvirt.dhcpservice;
9
10 import java.math.BigInteger;
11 import java.util.ArrayList;
12 import java.util.HashMap;
13 import java.util.List;
14
15 import org.apache.commons.lang3.tuple.ImmutablePair;
16 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
17 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
18 import org.opendaylight.genius.mdsalutil.ActionInfo;
19 import org.opendaylight.genius.mdsalutil.ActionType;
20 import org.opendaylight.genius.mdsalutil.FlowEntity;
21 import org.opendaylight.genius.mdsalutil.InstructionInfo;
22 import org.opendaylight.genius.mdsalutil.InstructionType;
23 import org.opendaylight.genius.mdsalutil.MDSALUtil;
24 import org.opendaylight.genius.mdsalutil.MatchInfo;
25 import org.opendaylight.genius.mdsalutil.NwConstants;
26 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
27 import org.opendaylight.netvirt.dhcpservice.api.DHCPMConstants;
28 import org.opendaylight.netvirt.neutronvpn.interfaces.INeutronVpnManager;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceBindings;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceTypeFlowBased;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflow;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.StypeOpenflowBuilder;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfo;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.ServicesInfoKey;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.ServiceModeIngress;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServicesKey;
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.opendaylight.yangtools.yang.binding.InstanceIdentifier;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46 public class DhcpManager implements AutoCloseable {
47
48     private static final Logger logger = LoggerFactory.getLogger(DhcpManager.class);
49     private final DataBroker broker;
50     IMdsalApiManager mdsalUtil;
51
52     private int dhcpOptLeaseTime = 0;
53     private int dhcpOptRenewalTime = 0;
54     private int dhcpOptRebindingTime = 0;
55     private String dhcpOptDefDomainName;
56     private INeutronVpnManager neutronVpnService;
57     // cache used to maintain DpnId and physical address for each interface.
58     private static HashMap<String, ImmutablePair<BigInteger, String>> interfaceToDpnIdMacAddress = new HashMap<>();
59
60     /**
61     * @param db - dataBroker reference
62     */
63     public DhcpManager(final DataBroker db) {
64         broker = db;
65         configureLeaseDuration(DHCPMConstants.DEFAULT_LEASE_TIME);
66     }
67
68     public void setMdsalManager(IMdsalApiManager mdsalManager) {
69         this.mdsalUtil = mdsalManager;
70     }
71
72     public void setNeutronVpnService(INeutronVpnManager neutronVpnService) {
73         logger.debug("Setting NeutronVpn dependency");
74         this.neutronVpnService = neutronVpnService;
75     }
76
77     @Override
78     public void close() throws Exception {
79         logger.info("DHCP Manager Closed");
80     }
81
82     public int setLeaseDuration(int leaseDuration) {
83         configureLeaseDuration(leaseDuration);
84         return getDhcpLeaseTime();
85     }
86
87     public String setDefaultDomain(String defaultDomain) {
88         this.dhcpOptDefDomainName = defaultDomain;
89         return getDhcpDefDomain();
90     }
91
92     protected int getDhcpLeaseTime() {
93         return this.dhcpOptLeaseTime;
94     }
95
96     protected int getDhcpRenewalTime() {
97         return this.dhcpOptLeaseTime;
98     }
99
100     protected int getDhcpRebindingTime() {
101         return this.dhcpOptLeaseTime;
102     }
103
104     protected String getDhcpDefDomain() {
105         return this.dhcpOptDefDomainName;
106     }
107
108     private void configureLeaseDuration(int leaseTime) {
109         this.dhcpOptLeaseTime = leaseTime;
110         if(leaseTime > 0) {
111             this.dhcpOptRenewalTime = this.dhcpOptLeaseTime/2;
112             this.dhcpOptRebindingTime = (this.dhcpOptLeaseTime*7)/8;
113         } else {
114             this.dhcpOptRenewalTime = -1;
115             this.dhcpOptRebindingTime = -1;
116         }
117     }
118
119     public Subnet getNeutronSubnet(Port nPort) {
120         if (nPort != null) {
121             try {
122                 return neutronVpnService.getNeutronSubnet(nPort.getFixedIps().get(0).getSubnetId());
123             } catch (Exception e) {
124                 logger.warn("Failed to get Neutron Subnet from Port: {}", e);
125             }
126         }
127         return null;
128     }
129
130     public Port getNeutronPort(String name) {
131         try {
132             return neutronVpnService.getNeutronPort(name);
133         } catch (IllegalArgumentException e) {
134             return null;
135         } catch (Exception ex) {
136             logger.trace("In getNeutronPort interface name passed {} exception message {}.", name, ex.getMessage());
137             return null;
138         }
139     }
140
141     public void installDhcpEntries(BigInteger dpnId, String vmMacAddress) {
142         DhcpServiceUtils.setupDhcpFlowEntry(dpnId, DHCPMConstants.DHCP_TABLE, vmMacAddress, NwConstants.ADD_FLOW, mdsalUtil);
143     }
144
145     public void unInstallDhcpEntries(BigInteger dpId, String vmMacAddress) {
146         DhcpServiceUtils.setupDhcpFlowEntry(dpId, DHCPMConstants.DHCP_TABLE, vmMacAddress, NwConstants.DEL_FLOW, mdsalUtil);
147     }
148
149     public void setupTableMissForDhcpTable(BigInteger dpId) {
150         List<MatchInfo> matches = new ArrayList<>();
151         List<InstructionInfo> instructions = new ArrayList<>();
152         List <ActionInfo> actionsInfos = new ArrayList<>();
153         actionsInfos.add(new ActionInfo(ActionType.nx_resubmit, new String[]{
154                 Short.toString(NwConstants.LPORT_DISPATCHER_TABLE)}));
155         instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
156         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, DHCPMConstants.DHCP_TABLE, "DHCPTableMissFlow",
157                 0, "DHCP Table Miss Flow", 0, 0,
158                 DHCPMConstants.COOKIE_DHCP_BASE, matches, instructions);
159         mdsalUtil.installFlow(flowEntity);
160         setupTableMissForHandlingExternalTunnel(dpId);
161     }
162
163     private void setupTableMissForHandlingExternalTunnel(BigInteger dpId) {
164         List<MatchInfo> matches = new ArrayList<>();
165         List<InstructionInfo> instructions = new ArrayList<>();
166         instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NwConstants.EXTERNAL_TUNNEL_TABLE }));
167
168         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.DHCP_TABLE_EXTERNAL_TUNNEL, "DHCPTableMissFlowForExternalTunnel",
169                 0, "DHCP Table Miss Flow For External Tunnel", 0, 0,
170                 DHCPMConstants.COOKIE_DHCP_BASE, matches, instructions);
171         mdsalUtil.installFlow(flowEntity);
172     }
173
174     public void updateInterfaceCache(String interfaceName, ImmutablePair<BigInteger, String> pair) {
175         interfaceToDpnIdMacAddress.put(interfaceName, pair);
176     }
177
178     public ImmutablePair<BigInteger, String> getInterfaceCache(String interfaceName) {
179         return interfaceToDpnIdMacAddress.get(interfaceName);
180     }
181
182     public void removeInterfaceCache(String interfaceName) {
183         interfaceToDpnIdMacAddress.remove(interfaceName);
184     }
185
186     public void bindDhcpService(String interfaceName, short tableId) {
187         int instructionKey = 0;
188         List<Instruction> instructions = new ArrayList<>();
189         instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(tableId, ++instructionKey));
190         BoundServices
191                 serviceInfo =
192                 getBoundServices(String.format("%s.%s", "dhcp", interfaceName),
193                         DHCPMConstants.DHCP_SERVICE_PRIORITY, DHCPMConstants.DEFAULT_FLOW_PRIORITY,
194                         DHCPMConstants.COOKIE_VM_INGRESS_TABLE, instructions);
195         MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
196                 buildServiceId(interfaceName, DHCPMConstants.DHCP_SERVICE_PRIORITY), serviceInfo);
197     }
198
199     private InstanceIdentifier buildServiceId(String interfaceName,
200                                               short dhcpServicePriority) {
201         return InstanceIdentifier.builder(ServiceBindings.class).child(ServicesInfo.class, new ServicesInfoKey(interfaceName, ServiceModeIngress.class))
202                 .child(BoundServices.class, new BoundServicesKey(dhcpServicePriority)).build();
203     }
204
205     public BoundServices getBoundServices(String serviceName, short servicePriority, int flowPriority,
206                                           BigInteger cookie, List<Instruction> instructions) {
207         StypeOpenflowBuilder augBuilder = new StypeOpenflowBuilder().setFlowCookie(cookie).setFlowPriority(flowPriority).setInstruction(instructions);
208         return new BoundServicesBuilder().setKey(new BoundServicesKey(servicePriority))
209                 .setServiceName(serviceName).setServicePriority(servicePriority)
210                 .setServiceType(ServiceTypeFlowBased.class).addAugmentation(StypeOpenflow.class, augBuilder.build()).build();
211     }
212
213     public void unbindDhcpService(String interfaceName) {
214         MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION,
215                 buildServiceId(interfaceName, DHCPMConstants.DHCP_SERVICE_PRIORITY));
216     }
217 }