54fd5ba4cbce0cd5efe143f5d763eed1cfe8b38d
[netvirt.git] / dhcpservice / impl / src / main / java / org / opendaylight / netvirt / 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.netvirt.dhcpservice;
9
10 import com.google.common.base.Optional;
11 import java.util.ArrayList;
12 import java.util.List;
13 import java.util.concurrent.ExecutionException;
14 import javax.annotation.PostConstruct;
15 import javax.annotation.PreDestroy;
16 import javax.inject.Inject;
17 import javax.inject.Named;
18 import javax.inject.Singleton;
19 import org.eclipse.jdt.annotation.Nullable;
20 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
21 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
22 import org.opendaylight.genius.infra.Datastore.Configuration;
23 import org.opendaylight.genius.infra.TypedReadWriteTransaction;
24 import org.opendaylight.genius.infra.TypedWriteTransaction;
25 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
26 import org.opendaylight.genius.mdsalutil.ActionInfo;
27 import org.opendaylight.genius.mdsalutil.FlowEntity;
28 import org.opendaylight.genius.mdsalutil.InstructionInfo;
29 import org.opendaylight.genius.mdsalutil.MDSALUtil;
30 import org.opendaylight.genius.mdsalutil.MatchInfo;
31 import org.opendaylight.genius.mdsalutil.NwConstants;
32 import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
33 import org.opendaylight.genius.mdsalutil.actions.ActionPuntToController;
34 import org.opendaylight.genius.mdsalutil.instructions.InstructionApplyActions;
35 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
36 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
37 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
38 import org.opendaylight.netvirt.dhcpservice.api.DhcpMConstants;
39 import org.opendaylight.netvirt.elanmanager.api.IElanService;
40 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.PortKey;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetKey;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.config.rev150710.DhcpserviceConfig;
51 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
52 import org.opendaylight.yangtools.yang.common.Uint64;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
55
56 @Singleton
57 public class DhcpManager {
58
59     private static final Logger LOG = LoggerFactory.getLogger(DhcpManager.class);
60     private final IMdsalApiManager mdsalUtil;
61     private final DhcpserviceConfig config;
62     private final DataBroker broker;
63     private final DhcpExternalTunnelManager dhcpExternalTunnelManager;
64     private final IInterfaceManager interfaceManager;
65     private final IElanService elanService;
66     private final JobCoordinator jobCoordinator;
67     private DhcpPortCache dhcpPortCache;
68     private final ItmRpcService itmRpcService;
69     private final DhcpServiceCounters dhcpServiceCounters;
70
71     private volatile int dhcpOptLeaseTime = 0;
72     private volatile String dhcpOptDefDomainName;
73     private DhcpInterfaceEventListener dhcpInterfaceEventListener;
74     private DhcpInterfaceConfigListener dhcpInterfaceConfigListener;
75
76     @Inject
77     public DhcpManager(final IMdsalApiManager mdsalApiManager,
78             final DhcpserviceConfig config, final DataBroker dataBroker,
79             final DhcpExternalTunnelManager dhcpExternalTunnelManager, final IInterfaceManager interfaceManager,
80             @Named("elanService") IElanService ielanService, final DhcpPortCache dhcpPortCache,
81             final JobCoordinator jobCoordinator, final ItmRpcService itmRpcService,
82             DhcpServiceCounters dhcpServiceCounters) {
83         this.mdsalUtil = mdsalApiManager;
84         this.config = config;
85         this.broker = dataBroker;
86         this.dhcpExternalTunnelManager = dhcpExternalTunnelManager;
87         this.interfaceManager = interfaceManager;
88         this.elanService = ielanService;
89         this.dhcpPortCache = dhcpPortCache;
90         this.jobCoordinator = jobCoordinator;
91         this.itmRpcService = itmRpcService;
92         this.dhcpServiceCounters = dhcpServiceCounters;
93         configureLeaseDuration(DhcpMConstants.DEFAULT_LEASE_TIME);
94     }
95
96     @PostConstruct
97     public void init() {
98         LOG.trace("Netvirt DHCP Manager Init .... {}",config.isControllerDhcpEnabled());
99         if (config.isControllerDhcpEnabled()) {
100             dhcpInterfaceEventListener = new DhcpInterfaceEventListener(this, broker, dhcpExternalTunnelManager,
101                     interfaceManager, elanService, dhcpPortCache, jobCoordinator, itmRpcService);
102             dhcpInterfaceConfigListener = new DhcpInterfaceConfigListener(broker, dhcpExternalTunnelManager, this,
103                     jobCoordinator);
104             LOG.info("DHCP Service initialized");
105         }
106     }
107
108     @PreDestroy
109     public void close() {
110         if (dhcpInterfaceEventListener != null) {
111             dhcpInterfaceEventListener.close();
112         }
113         if (dhcpInterfaceConfigListener != null) {
114             dhcpInterfaceConfigListener.close();
115         }
116         LOG.info("DHCP Service closed");
117     }
118
119     public int setLeaseDuration(int leaseDuration) {
120         configureLeaseDuration(leaseDuration);
121         return getDhcpLeaseTime();
122     }
123
124     public String setDefaultDomain(String defaultDomain) {
125         this.dhcpOptDefDomainName = defaultDomain;
126         return getDhcpDefDomain();
127     }
128
129     public int getDhcpLeaseTime() {
130         return this.dhcpOptLeaseTime;
131     }
132
133     public int getDhcpRenewalTime() {
134         return this.dhcpOptLeaseTime;
135     }
136
137     public int getDhcpRebindingTime() {
138         return this.dhcpOptLeaseTime;
139     }
140
141     public String getDhcpDefDomain() {
142         return this.dhcpOptDefDomainName;
143     }
144
145     private void configureLeaseDuration(int leaseTime) {
146         this.dhcpOptLeaseTime = leaseTime;
147     }
148
149     @Nullable
150     public Subnet getNeutronSubnet(Port port) {
151         if (port != null) {
152             // DHCP Service is only interested in IPv4 IPs/Subnets
153             return getNeutronSubnet(port.getFixedIps());
154         }
155         return null;
156     }
157
158     @Nullable
159     public Subnet getNeutronSubnet(List<FixedIps> fixedIps) {
160         for (FixedIps fixedIp: fixedIps) {
161             if (fixedIp.getIpAddress().getIpv4Address() != null) {
162                 return getNeutronSubnet(fixedIp.getSubnetId());
163             }
164         }
165         return null;
166     }
167
168     @Nullable
169     private Subnet getNeutronSubnet(Uuid subnetId) {
170         Subnet subnet = null;
171         InstanceIdentifier<Subnet> inst = InstanceIdentifier.create(Neutron.class).child(Subnets.class).child(Subnet
172                 .class, new SubnetKey(subnetId));
173         Optional<Subnet> sn = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, inst);
174         if (sn.isPresent()) {
175             subnet = sn.get();
176         }
177         LOG.trace("Subnet {} = {}", subnetId, subnet);
178         return subnet;
179     }
180
181     @Nullable
182     public Port getNeutronPort(String name) {
183         Port prt = null;
184         InstanceIdentifier<Port> inst = InstanceIdentifier.create(Neutron.class).child(Ports.class).child(Port.class,
185                 new PortKey(new Uuid(name)));
186         Optional<Port> port = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, inst);
187         if (port.isPresent()) {
188             prt = port.get();
189         }
190         LOG.trace("Port {} = {}", name, prt);
191         return prt;
192     }
193
194     public void installDhcpEntries(@Nullable Uint64 dpnId, @Nullable String vmMacAddress,
195             TypedReadWriteTransaction<Configuration> tx) throws ExecutionException, InterruptedException {
196         DhcpServiceUtils.setupDhcpFlowEntry(dpnId, NwConstants.DHCP_TABLE, vmMacAddress, NwConstants.ADD_FLOW,
197                 mdsalUtil, dhcpServiceCounters, tx);
198     }
199
200     public void unInstallDhcpEntries(@Nullable Uint64 dpId, @Nullable String vmMacAddress,
201             TypedReadWriteTransaction<Configuration> tx) throws ExecutionException, InterruptedException {
202         DhcpServiceUtils.setupDhcpFlowEntry(dpId, NwConstants.DHCP_TABLE, vmMacAddress, NwConstants.DEL_FLOW,
203                 mdsalUtil, dhcpServiceCounters, tx);
204     }
205
206     public void setupDefaultDhcpFlows(TypedWriteTransaction<Configuration> tx, Uint64 dpId) {
207         setupTableMissForDhcpTable(tx, dpId);
208         if (config.isDhcpDynamicAllocationPoolEnabled()) {
209             setupDhcpAllocationPoolFlow(tx, dpId);
210         }
211     }
212
213     private void setupTableMissForDhcpTable(TypedWriteTransaction<Configuration> tx, Uint64 dpId) {
214         List<MatchInfo> matches = new ArrayList<>();
215         List<InstructionInfo> instructions = new ArrayList<>();
216         List<ActionInfo> actionsInfos = new ArrayList<>();
217         actionsInfos.add(new ActionNxResubmit(NwConstants.LPORT_DISPATCHER_TABLE));
218         instructions.add(new InstructionApplyActions(actionsInfos));
219         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.DHCP_TABLE, "DHCPTableMissFlow",
220                 0, "DHCP Table Miss Flow", 0, 0,
221                 DhcpMConstants.COOKIE_DHCP_BASE, matches, instructions);
222         dhcpServiceCounters.installDhcpTableMissFlow();
223         mdsalUtil.addFlow(tx, flowEntity);
224         setupTableMissForHandlingExternalTunnel(tx, dpId);
225     }
226
227     private void setupDhcpAllocationPoolFlow(TypedWriteTransaction<Configuration> tx, Uint64 dpId) {
228         List<MatchInfo> matches = DhcpServiceUtils.getDhcpMatch();
229         List<InstructionInfo> instructions = new ArrayList<>();
230         List<ActionInfo> actionsInfos = new ArrayList<>();
231         actionsInfos.add(new ActionPuntToController());
232         instructions.add(new InstructionApplyActions(actionsInfos));
233         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.DHCP_TABLE,
234                 "DhcpAllocationPoolFlow", DhcpMConstants.DEFAULT_DHCP_ALLOCATION_POOL_FLOW_PRIORITY,
235                 "Dhcp Allocation Pool Flow", 0, 0, DhcpMConstants.COOKIE_DHCP_BASE, matches, instructions);
236         LOG.trace("Installing DHCP Allocation Pool Flow DpId {}", dpId);
237         dhcpServiceCounters.installDhcpFlow();
238         mdsalUtil.addFlow(tx, flowEntity);
239     }
240
241     private void setupTableMissForHandlingExternalTunnel(TypedWriteTransaction<Configuration> tx, Uint64 dpId) {
242         List<MatchInfo> matches = new ArrayList<>();
243         List<InstructionInfo> instructions = new ArrayList<>();
244         instructions.add(new InstructionGotoTable(NwConstants.EXTERNAL_TUNNEL_TABLE));
245
246         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.DHCP_TABLE_EXTERNAL_TUNNEL,
247                 "DHCPTableMissFlowForExternalTunnel",
248                 0, "DHCP Table Miss Flow For External Tunnel", 0, 0,
249                 DhcpMConstants.COOKIE_DHCP_BASE, matches, instructions);
250         dhcpServiceCounters.installDhcpTableMissFlowForExternalTable();
251         mdsalUtil.addFlow(tx, flowEntity);
252     }
253 }