ac3c99ab3681e54c2799a661470229decf35bce9
[netvirt.git] / vpnservice / dhcpservice / dhcpservice-impl / src / main / java / org / opendaylight / netvirt / dhcpservice / DhcpServiceUtils.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
9 package org.opendaylight.netvirt.dhcpservice;
10
11 import java.math.BigInteger;
12 import java.util.ArrayList;
13 import java.util.LinkedList;
14 import java.util.List;
15
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.netvirt.dhcpservice.api.DHCPMConstants;
19 import org.opendaylight.genius.mdsalutil.ActionInfo;
20 import org.opendaylight.genius.mdsalutil.ActionType;
21 import org.opendaylight.genius.mdsalutil.FlowEntity;
22 import org.opendaylight.genius.mdsalutil.InstructionInfo;
23 import org.opendaylight.genius.mdsalutil.InstructionType;
24 import org.opendaylight.genius.mdsalutil.MDSALUtil;
25 import org.opendaylight.genius.mdsalutil.MatchFieldType;
26 import org.opendaylight.genius.mdsalutil.MatchInfo;
27 import org.opendaylight.genius.mdsalutil.NwConstants;
28 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
29 import org.opendaylight.genius.mdsalutil.packet.IPProtocols;
30 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronUtils;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.NetworkTypeVxlan;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.Networks;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.NetworkKey;
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.rev150712.Neutron;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanDpnInterfaces;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesList;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesListKey;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfaces;
50 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
53
54 import com.google.common.base.Optional;
55
56 public class DhcpServiceUtils {
57
58     private static final Logger logger = LoggerFactory.getLogger(DhcpServiceUtils.class);
59
60     public static Interface getInterfaceFromConfigDS(String interfaceName, DataBroker dataBroker) {
61         InterfaceKey interfaceKey = new InterfaceKey(interfaceName);
62         InstanceIdentifier<Interface> interfaceId = getInterfaceIdentifier(interfaceKey);
63         Optional<Interface> interfaceOptional = MDSALUtil.read(LogicalDatastoreType.CONFIGURATION, interfaceId, dataBroker);
64         if (!interfaceOptional.isPresent()) {
65             return null;
66         }
67         return interfaceOptional.get();
68     }
69
70     private static InstanceIdentifier<Interface> getInterfaceIdentifier(InterfaceKey interfaceKey) {
71         InstanceIdentifier.InstanceIdentifierBuilder<Interface> interfaceInstanceIdentifierBuilder =
72                 InstanceIdentifier.builder(Interfaces.class).child(Interface.class, interfaceKey);
73         return interfaceInstanceIdentifierBuilder.build();
74     }
75
76     public static void setupDhcpFlowEntry(BigInteger dpId, short tableId, String vmMacAddress, int addOrRemove, IMdsalApiManager mdsalUtil) {
77         if (dpId == null || dpId.equals(DHCPMConstants.INVALID_DPID) || vmMacAddress == null) {
78             return;
79         }
80         List<MatchInfo> matches = getDhcpMatch(vmMacAddress);
81
82         List<InstructionInfo> instructions = new ArrayList<>();
83         List<ActionInfo> actionsInfos = new ArrayList<>();
84
85         // Punt to controller
86         actionsInfos.add(new ActionInfo(ActionType.punt_to_controller,
87                 new String[] {}));
88         instructions.add(new InstructionInfo(InstructionType.write_actions,
89                 actionsInfos));
90         if (addOrRemove == NwConstants.DEL_FLOW) {
91             FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId,
92                     getDhcpFlowRef(dpId, tableId, vmMacAddress),
93                     DHCPMConstants.DEFAULT_DHCP_FLOW_PRIORITY, "DHCP", 0, 0,
94                     DHCPMConstants.COOKIE_DHCP_BASE, matches, null);
95             logger.trace("Removing DHCP Flow DpId {}, vmMacAddress {}", dpId, vmMacAddress);
96             mdsalUtil.removeFlow(flowEntity);
97         } else {
98             FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId,
99                     getDhcpFlowRef(dpId, tableId, vmMacAddress),DHCPMConstants.DEFAULT_DHCP_FLOW_PRIORITY, "DHCP", 0, 0,
100                     DHCPMConstants.COOKIE_DHCP_BASE, matches, instructions);
101             logger.trace("Installing DHCP Flow DpId {}, vmMacAddress {}", dpId, vmMacAddress);
102             mdsalUtil.installFlow(flowEntity);
103         }
104     }
105
106     private static String getDhcpFlowRef(BigInteger dpId, long tableId, String vmMacAddress) {
107         return new StringBuffer().append(DHCPMConstants.FLOWID_PREFIX)
108                 .append(dpId).append(NwConstants.FLOWID_SEPARATOR)
109                 .append(tableId).append(NwConstants.FLOWID_SEPARATOR)
110                 .append(vmMacAddress).toString();
111     }
112
113     public static void setupDhcpDropAction(BigInteger dpId, short tableId, String vmMacAddress, int addOrRemove, IMdsalApiManager mdsalUtil) {
114         if (dpId == null || dpId.equals(DHCPMConstants.INVALID_DPID) || vmMacAddress == null) {
115             return;
116         }
117         List<MatchInfo> matches = getDhcpMatch(vmMacAddress);
118
119         List<ActionInfo> actionsInfos = new ArrayList<>();
120         List<InstructionInfo> instructions = new ArrayList<>();
121         instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfos));
122         // Drop Action
123         actionsInfos.add(new ActionInfo(ActionType.drop_action,
124                 new String[] {}));
125         if (addOrRemove == NwConstants.DEL_FLOW) {
126             FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId,
127                     getDhcpFlowRef(dpId, tableId, vmMacAddress),
128                     DHCPMConstants.DEFAULT_DHCP_FLOW_PRIORITY, "DHCP", 0, 0,
129                     DHCPMConstants.COOKIE_DHCP_BASE, matches, null);
130             logger.trace("Removing DHCP Drop Flow DpId {}, vmMacAddress {}", dpId, vmMacAddress);
131             mdsalUtil.removeFlow(flowEntity);
132         } else {
133             FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId,
134                     getDhcpFlowRef(dpId, tableId, vmMacAddress),DHCPMConstants.DEFAULT_DHCP_FLOW_PRIORITY, "DHCP", 0, 0,
135                     DHCPMConstants.COOKIE_DHCP_BASE, matches, instructions);
136             logger.trace("Installing DHCP Drop Flow DpId {}, vmMacAddress {}", dpId, vmMacAddress);
137             mdsalUtil.installFlow(flowEntity);
138         }
139     }
140
141     private static List<MatchInfo> getDhcpMatch(String vmMacAddress) {
142         List<MatchInfo> matches = new ArrayList<>();
143         matches.add(new MatchInfo(MatchFieldType.eth_type,
144                 new long[] { NwConstants.ETHTYPE_IPV4 }));
145         matches.add(new MatchInfo(MatchFieldType.ip_proto,
146                 new long[] { IPProtocols.UDP.intValue() }));
147         matches.add(new MatchInfo(MatchFieldType.udp_src,
148                 new long[] { DHCPMConstants.dhcpClientPort }));
149         matches.add(new MatchInfo(MatchFieldType.udp_dst,
150                 new long[] { DHCPMConstants.dhcpServerPort }));
151         matches.add(new MatchInfo(MatchFieldType.eth_src,
152                 new String[] { vmMacAddress }));
153         return matches;
154     }
155
156     public static List<BigInteger> getListOfDpns(DataBroker broker) {
157         List<BigInteger> dpnsList = new LinkedList<>();
158         InstanceIdentifier<Nodes> nodesInstanceIdentifier = InstanceIdentifier.builder(Nodes.class).build();
159         Optional<Nodes> nodesOptional = MDSALUtil.read(broker, LogicalDatastoreType.OPERATIONAL, nodesInstanceIdentifier);
160         if (!nodesOptional.isPresent()) {
161             return dpnsList;
162         }
163         Nodes nodes = nodesOptional.get();
164         List<Node> nodeList = nodes.getNode();
165         for (Node node : nodeList) {
166             NodeId nodeId = node.getId();
167             if (nodeId == null) {
168                 continue;
169             }
170             BigInteger dpnId = MDSALUtil.getDpnIdFromNodeName(nodeId);
171             dpnsList.add(dpnId);
172         }
173         return dpnsList;
174     }
175
176     public static List<BigInteger> getDpnsForElan(String elanInstanceName, DataBroker broker) {
177         List<BigInteger> elanDpns = new LinkedList<>();
178         InstanceIdentifier<ElanDpnInterfacesList> elanDpnInstanceIdentifier = InstanceIdentifier.builder(ElanDpnInterfaces.class).child(ElanDpnInterfacesList.class, new ElanDpnInterfacesListKey(elanInstanceName)).build();
179         Optional<ElanDpnInterfacesList> elanDpnOptional = MDSALUtil.read(broker, LogicalDatastoreType.OPERATIONAL, elanDpnInstanceIdentifier);
180         if (elanDpnOptional.isPresent()) {
181             List<DpnInterfaces> dpns = elanDpnOptional.get().getDpnInterfaces();
182             for (DpnInterfaces dpnInterfaces : dpns) {
183                 elanDpns.add(dpnInterfaces.getDpId());
184             }
185         }
186         return elanDpns;
187     }
188
189     public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface getInterfaceFromOperationalDS(String interfaceName, DataBroker dataBroker) {
190         org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey interfaceKey = new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(interfaceName);
191         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> interfaceId = InstanceIdentifier.builder(InterfacesState.class).child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class, interfaceKey).build();
192         Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> interfaceOptional = MDSALUtil.read(LogicalDatastoreType.OPERATIONAL, interfaceId, dataBroker);
193         if (!interfaceOptional.isPresent()) {
194             return null;
195         }
196         return interfaceOptional.get();
197     }
198
199
200     public static String getSegmentationId(Uuid networkId, DataBroker broker) {
201         InstanceIdentifier<Network> inst = InstanceIdentifier.create(Neutron.class).child(Networks.class).child
202                 (Network.class, new NetworkKey(networkId));
203         Optional<Network> optionalNetwork = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, inst);
204         if (!optionalNetwork.isPresent()) {
205             return null;
206         }
207         Network network = optionalNetwork.get();
208         String segmentationId = NeutronUtils.getSegmentationIdFromNeutronNetwork(network, NetworkTypeVxlan.class);
209         return segmentationId;
210     }
211
212     public static String getNodeIdFromDpnId(BigInteger dpnId) {
213         return MDSALUtil.NODE_PREFIX + MDSALUtil.SEPARATOR + dpnId.toString();
214     }
215
216     public static String getTrunkPortMacAddress(String parentRefName,
217             DataBroker broker) {
218         InstanceIdentifier<Port> portInstanceIdentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class).child(Port.class);
219         Optional<Port> trunkPort = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, portInstanceIdentifier);
220         if (!trunkPort.isPresent()) {
221             logger.warn("Trunk port {} not available for sub-port", parentRefName);
222             return null;
223         }
224         return trunkPort.get().getMacAddress().getValue();
225     }
226 }