/* * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.vpnservice.dhcpservice; import java.math.BigInteger; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.vpnservice.dhcpservice.api.DHCPMConstants; import org.opendaylight.vpnservice.mdsalutil.ActionInfo; import org.opendaylight.vpnservice.mdsalutil.ActionType; import org.opendaylight.vpnservice.mdsalutil.FlowEntity; import org.opendaylight.vpnservice.mdsalutil.InstructionInfo; import org.opendaylight.vpnservice.mdsalutil.InstructionType; import org.opendaylight.vpnservice.mdsalutil.MDSALUtil; import org.opendaylight.vpnservice.mdsalutil.MatchFieldType; import org.opendaylight.vpnservice.mdsalutil.MatchInfo; import org.opendaylight.vpnservice.mdsalutil.NwConstants; import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager; import org.opendaylight.vpnservice.mdsalutil.packet.IPProtocols; import org.opendaylight.vpnservice.neutronvpn.api.utils.NeutronUtils; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.Networks; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.NetworkKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port; import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.ElanDpnInterfaces; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesList; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.dpn.interfaces.ElanDpnInterfacesListKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfaces; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Optional; public class DhcpServiceUtils { private static final Logger logger = LoggerFactory.getLogger(DhcpServiceUtils.class); public static Interface getInterfaceFromConfigDS(String interfaceName, DataBroker dataBroker) { InterfaceKey interfaceKey = new InterfaceKey(interfaceName); InstanceIdentifier interfaceId = getInterfaceIdentifier(interfaceKey); Optional interfaceOptional = MDSALUtil.read(LogicalDatastoreType.CONFIGURATION, interfaceId, dataBroker); if (!interfaceOptional.isPresent()) { return null; } return interfaceOptional.get(); } private static InstanceIdentifier getInterfaceIdentifier(InterfaceKey interfaceKey) { InstanceIdentifier.InstanceIdentifierBuilder interfaceInstanceIdentifierBuilder = InstanceIdentifier.builder(Interfaces.class).child(Interface.class, interfaceKey); return interfaceInstanceIdentifierBuilder.build(); } public static void setupDhcpFlowEntry(BigInteger dpId, short tableId, String vmMacAddress, int addOrRemove, IMdsalApiManager mdsalUtil) { if (dpId == null || dpId.equals(DHCPMConstants.INVALID_DPID) || vmMacAddress == null) { return; } List matches = getDhcpMatch(vmMacAddress); List instructions = new ArrayList(); List actionsInfos = new ArrayList(); // Punt to controller actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {})); instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfos)); if (addOrRemove == NwConstants.DEL_FLOW) { FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId, getDhcpFlowRef(dpId, tableId, vmMacAddress), DHCPMConstants.DEFAULT_DHCP_FLOW_PRIORITY, "DHCP", 0, 0, DHCPMConstants.COOKIE_DHCP_BASE, matches, null); logger.trace("Removing DHCP Flow DpId {}, vmMacAddress {}", dpId, vmMacAddress); mdsalUtil.removeFlow(flowEntity); } else { FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId, getDhcpFlowRef(dpId, tableId, vmMacAddress),DHCPMConstants.DEFAULT_DHCP_FLOW_PRIORITY, "DHCP", 0, 0, DHCPMConstants.COOKIE_DHCP_BASE, matches, instructions); logger.trace("Installing DHCP Flow DpId {}, vmMacAddress {}", dpId, vmMacAddress); mdsalUtil.installFlow(flowEntity); } } private static String getDhcpFlowRef(BigInteger dpId, long tableId, String vmMacAddress) { return new StringBuffer().append(DHCPMConstants.FLOWID_PREFIX) .append(dpId).append(NwConstants.FLOWID_SEPARATOR) .append(tableId).append(NwConstants.FLOWID_SEPARATOR) .append(vmMacAddress).toString(); } public static void setupDhcpDropAction(BigInteger dpId, short tableId, String vmMacAddress, int addOrRemove, IMdsalApiManager mdsalUtil) { if (dpId == null || dpId.equals(DHCPMConstants.INVALID_DPID) || vmMacAddress == null) { return; } List matches = getDhcpMatch(vmMacAddress); List actionsInfos = new ArrayList(); List instructions = new ArrayList(); instructions.add(new InstructionInfo(InstructionType.write_actions, actionsInfos)); // Drop Action actionsInfos.add(new ActionInfo(ActionType.drop_action, new String[] {})); if (addOrRemove == NwConstants.DEL_FLOW) { FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId, getDhcpFlowRef(dpId, tableId, vmMacAddress), DHCPMConstants.DEFAULT_DHCP_FLOW_PRIORITY, "DHCP", 0, 0, DHCPMConstants.COOKIE_DHCP_BASE, matches, null); logger.trace("Removing DHCP Flow DpId {}, vmMacAddress {}", dpId, vmMacAddress); mdsalUtil.removeFlow(flowEntity); } else { FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, tableId, getDhcpFlowRef(dpId, tableId, vmMacAddress),DHCPMConstants.DEFAULT_DHCP_FLOW_PRIORITY, "DHCP", 0, 0, DHCPMConstants.COOKIE_DHCP_BASE, matches, instructions); logger.trace("Installing DHCP Flow DpId {}, vmMacAddress {}", dpId, vmMacAddress); mdsalUtil.installFlow(flowEntity); } } private static List getDhcpMatch(String vmMacAddress) { List matches = new ArrayList(); matches.add(new MatchInfo(MatchFieldType.eth_type, new long[] { NwConstants.ETHTYPE_IPV4 })); matches.add(new MatchInfo(MatchFieldType.ip_proto, new long[] { IPProtocols.UDP.intValue() })); matches.add(new MatchInfo(MatchFieldType.udp_src, new long[] { DHCPMConstants.dhcpClientPort })); matches.add(new MatchInfo(MatchFieldType.udp_dst, new long[] { DHCPMConstants.dhcpServerPort })); matches.add(new MatchInfo(MatchFieldType.eth_src, new String[] { vmMacAddress })); return matches; } public static List getListOfDpns(DataBroker broker) { List dpnsList = new LinkedList(); InstanceIdentifier nodesInstanceIdentifier = InstanceIdentifier.builder(Nodes.class).build(); Optional nodesOptional = MDSALUtil.read(broker, LogicalDatastoreType.OPERATIONAL, nodesInstanceIdentifier); if (!nodesOptional.isPresent()) { return dpnsList; } Nodes nodes = nodesOptional.get(); List nodeList = nodes.getNode(); for (Node node : nodeList) { NodeId nodeId = node.getId(); if (nodeId == null) { continue; } BigInteger dpnId = MDSALUtil.getDpnIdFromNodeName(nodeId); dpnsList.add(dpnId); } return dpnsList; } public static List getDpnsForElan(String elanInstanceName, DataBroker broker) { List elanDpns = new LinkedList(); InstanceIdentifier elanDpnInstanceIdentifier = InstanceIdentifier.builder(ElanDpnInterfaces.class).child(ElanDpnInterfacesList.class, new ElanDpnInterfacesListKey(elanInstanceName)).build(); Optional elanDpnOptional = MDSALUtil.read(broker, LogicalDatastoreType.OPERATIONAL, elanDpnInstanceIdentifier); if (elanDpnOptional.isPresent()) { List dpns = elanDpnOptional.get().getDpnInterfaces(); for (DpnInterfaces dpnInterfaces : dpns) { elanDpns.add(dpnInterfaces.getDpId()); } } return elanDpns; } public static org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface getInterfaceFromOperationalDS(String interfaceName, DataBroker dataBroker) { 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); InstanceIdentifier 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(); Optional interfaceOptional = MDSALUtil.read(LogicalDatastoreType.OPERATIONAL, interfaceId, dataBroker); if (!interfaceOptional.isPresent()) { return null; } return interfaceOptional.get(); } public static String getSegmentationId(Uuid networkId, DataBroker broker) { InstanceIdentifier inst = InstanceIdentifier.create(Neutron.class).child(Networks.class).child (Network.class, new NetworkKey(networkId)); Optional optionalNetwork = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, inst); if (!optionalNetwork.isPresent()) { return null; } Network network = optionalNetwork.get(); String segmentationId = NeutronUtils.getSegmentationIdFromNeutronNetwork(network); return segmentationId; } public static String getNodeIdFromDpnId(BigInteger dpnId) { return MDSALUtil.NODE_PREFIX + MDSALUtil.SEPARATOR + dpnId.toString(); } public static String getTrunkPortMacAddress(String parentRefName, DataBroker broker) { InstanceIdentifier portInstanceIdentifier = InstanceIdentifier.create(Neutron.class).child(Ports.class).child(Port.class); Optional trunkPort = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, portInstanceIdentifier); if (!trunkPort.isPresent()) { logger.warn("Trunk port {} not available for sub-port", parentRefName); return null; } return trunkPort.get().getMacAddress(); } }