public final class DHCPMConstants {
- // DHCP Service Table Ids
- public static final short DHCP_TABLE = 0;
- public static final short L3_FIB_TABLE = 20;
-
public static final long DHCP_TABLE_MAX_ENTRY = 10000;
public static final int DEFAULT_DHCP_FLOW_PRIORITY = 50;
public static final int DEFAULT_LEASE_TIME = 86400;
public static final String DEFAULT_DOMAIN_NAME = "openstacklocal";
+
+ public static final BigInteger INVALID_DPID = new BigInteger("-1");
}
"Initial revision for DHCP Service module";
}
+ container interface-name-mac-addresses {
+ config false;
+ description
+ "Container to hold list of interface names and MAC address";
+
+ list interface-name-mac-address {
+ max-elements "unbounded";
+ min-elements "0";
+ key "interface-name";
+ description
+ "Specifies the name of the interface";
+
+ leaf interface-name {
+ type string;
+ description
+ "The name of the interface.";
+ }
+
+ leaf mac-address {
+ type string;
+ description
+ "The VM mac address for the interface.";
+ }
+ }
+ }
}
\ No newline at end of file
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
</dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>interfacemgr-api</artifactId>
+ <version>${vpnservices.version}</version>
+ </dependency>
</dependencies>
</project>
--- /dev/null
+/*
+ * 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.List;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener;
+import org.opendaylight.vpnservice.mdsalutil.MDSALDataStoreUtils;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+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.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710.InterfaceNameMacAddresses;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710._interface.name.mac.addresses.InterfaceNameMacAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710._interface.name.mac.addresses.InterfaceNameMacAddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.api.rev150710._interface.name.mac.addresses.InterfaceNameMacAddressKey;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.FutureCallback;
+
+public class DhcpInterfaceEventListener extends AbstractDataChangeListener<Interface> implements AutoCloseable {
+
+ private static final Logger logger = LoggerFactory.getLogger(DhcpInterfaceEventListener.class);
+ private DhcpManager dhcpManager;
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private DataBroker dataBroker;
+ private static final FutureCallback<Void> DEFAULT_CALLBACK = new FutureCallback<Void>() {
+ public void onSuccess(Void result) {
+ logger.debug("Success in Datastore write operation");
+ }
+
+ public void onFailure(Throwable error) {
+ logger.error("Error in Datastore write operation", error);
+ }
+ };
+
+ public DhcpInterfaceEventListener(DhcpManager dhcpManager, DataBroker dataBroker) {
+ super(Interface.class);
+ this.dhcpManager = dhcpManager;
+ this.dataBroker = dataBroker;
+ registerListener();
+ }
+
+ private void registerListener() {
+ try {
+ listenerRegistration = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+ getWildCardPath(), DhcpInterfaceEventListener.this, DataChangeScope.SUBTREE);
+ } catch (final Exception e) {
+ logger.error("DhcpInterfaceEventListener DataChange listener registration fail!", e);
+ throw new IllegalStateException("DhcpInterfaceEventListener registration Listener failed.", e);
+ }
+ }
+
+ private InstanceIdentifier<Interface> getWildCardPath() {
+ return InstanceIdentifier.create(InterfacesState.class).child(Interface.class);
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ try {
+ listenerRegistration.close();
+ } catch (final Exception e) {
+ logger.error("Error when cleaning up DataChangeListener.", e);
+ }
+ listenerRegistration = null;
+ }
+ logger.info("Interface Manager Closed");
+ }
+
+
+ @Override
+ protected void remove(InstanceIdentifier<Interface> identifier,
+ Interface del) {
+ String interfaceName = del.getName();
+ List<String> ofportIds = del.getLowerLayerIf();
+ NodeConnectorId nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
+ BigInteger dpId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId));
+ logger.trace("Received remove DCN for interface {} dpId {}", interfaceName, dpId);
+ unInstallDhcpEntries(interfaceName, dpId);
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Interface> identifier,
+ Interface original, Interface update) {
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Interface> identifier, Interface add) {
+ String interfaceName = add.getName();
+ List<String> ofportIds = add.getLowerLayerIf();
+ NodeConnectorId nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
+ BigInteger dpId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId));
+ logger.trace("Received add DCN for interface {}, dpid{}", interfaceName, dpId);
+ installDhcpEntries(interfaceName, dpId);
+ }
+
+ private String getNeutronMacAddress(String interfaceName) {
+ Port port = dhcpManager.getNeutronPort(interfaceName);
+ if (port!=null) {
+ logger.trace("Port found in neutron. Interface Name {}, port {}", interfaceName, port);
+ return port.getMacAddress();
+ }
+ logger.trace("Port not found in neutron. Interface Name {}, vlanId {}", interfaceName);
+ return null;
+ }
+
+ private void unInstallDhcpEntries(String interfaceName, BigInteger dpId) {
+ String vmMacAddress = getAndRemoveVmMacAddress(interfaceName);
+ dhcpManager.unInstallDhcpEntries(dpId, vmMacAddress);
+ }
+
+ private void installDhcpEntries(String interfaceName, BigInteger dpId) {
+ String vmMacAddress = getAndUpdateVmMacAddress(interfaceName);
+ dhcpManager.installDhcpEntries(dpId, vmMacAddress);
+ }
+
+ private String getAndUpdateVmMacAddress(String interfaceName) {
+ InstanceIdentifier<InterfaceNameMacAddress> instanceIdentifier = InstanceIdentifier.builder(InterfaceNameMacAddresses.class).child(InterfaceNameMacAddress.class, new InterfaceNameMacAddressKey(interfaceName)).build();
+ Optional<InterfaceNameMacAddress> existingEntry = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, instanceIdentifier);
+ if (!existingEntry.isPresent()) {
+ logger.trace("Entry for interface {} missing in InterfaceNameVmMacAddress map", interfaceName);
+ String vmMacAddress = getNeutronMacAddress(interfaceName);
+ if (vmMacAddress==null || vmMacAddress.isEmpty()) {
+ return null;
+ }
+ logger.trace("Updating InterfaceNameVmMacAddress map with {}, {}", interfaceName,vmMacAddress);
+ InterfaceNameMacAddress interfaceNameMacAddress = new InterfaceNameMacAddressBuilder().setKey(new InterfaceNameMacAddressKey(interfaceName)).setInterfaceName(interfaceName).setMacAddress(vmMacAddress).build();
+ MDSALUtil.syncUpdate(dataBroker, LogicalDatastoreType.OPERATIONAL, instanceIdentifier, interfaceNameMacAddress);
+ return vmMacAddress;
+ }
+ return existingEntry.get().getMacAddress();
+ }
+
+ private String getAndRemoveVmMacAddress(String interfaceName) {
+ InstanceIdentifier<InterfaceNameMacAddress> instanceIdentifier = InstanceIdentifier.builder(InterfaceNameMacAddresses.class).child(InterfaceNameMacAddress.class, new InterfaceNameMacAddressKey(interfaceName)).build();
+ Optional<InterfaceNameMacAddress> existingEntry = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, instanceIdentifier);
+ if (existingEntry.isPresent()) {
+ String vmMacAddress = existingEntry.get().getMacAddress();
+ logger.trace("Entry for interface found in InterfaceNameVmMacAddress map {}, {}", interfaceName, vmMacAddress);
+ MDSALDataStoreUtils.asyncRemove(dataBroker, LogicalDatastoreType.OPERATIONAL, instanceIdentifier, DEFAULT_CALLBACK);
+ return vmMacAddress;
+ }
+ logger.trace("Entry for interface {} missing in InterfaceNameVmMacAddress map", interfaceName);
+ return null;
+ }
+}
package org.opendaylight.vpnservice.dhcpservice;
import org.opendaylight.vpnservice.neutronvpn.interfaces.INeutronVpnManager;
-
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
+
import com.google.common.base.Optional;
+
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
+
import com.google.common.util.concurrent.FutureCallback;
+
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.vpnservice.dhcpservice.api.DHCPMConstants;
import org.opendaylight.vpnservice.mdsalutil.ActionInfo;
public void installDhcpEntries(BigInteger dpnId) {
logger.debug("Installing Default DHCP Flow tp DPN: {}", dpnId);
- setupDefaultDhcpFlow(dpnId, DHCPMConstants.DHCP_TABLE, NwConstants.ADD_FLOW);
+ setupDefaultDhcpFlow(dpnId, NwConstants.DHCP_TABLE, NwConstants.ADD_FLOW);
}
private void setupDefaultDhcpFlow(BigInteger dpId, short tableId, int addOrRemove) {
return neutronVpnService.getNeutronPort(name);
}
+ public void installDhcpEntries(BigInteger dpnId, String vmMacAddress) {
+ setupDhcpFlowEntry(dpnId, NwConstants.DHCP_TABLE, vmMacAddress, NwConstants.ADD_FLOW);
+ }
+
+ private void setupDhcpFlowEntry(BigInteger dpId, short tableId, String vmMacAddress, int addOrRemove) {
+ if (dpId == null || dpId == DHCPMConstants.INVALID_DPID || vmMacAddress == null) {
+ return;
+ }
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+
+ 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 }));
+
+ List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
+ List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
+
+ // 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 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 void unInstallDhcpEntries(BigInteger dpId, String vmMacAddress) {
+ setupDhcpFlowEntry(dpId, NwConstants.DHCP_TABLE, vmMacAddress, NwConstants.DEL_FLOW);
+ }
+
+ public void setupTableMissForDhcpTable(BigInteger dpId) {
+ List<MatchInfo> matches = new ArrayList<MatchInfo>();
+ List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
+ instructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { NwConstants.LPORT_DISPATCHER_TABLE }));
+
+ FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.DHCP_TABLE, "DHCPTableMissFlow",
+ 0, "DHCP Table Miss Flow", 0, 0,
+ DHCPMConstants.COOKIE_DHCP_BASE, matches, instructions);
+ mdsalUtil.installFlow(flowEntity);
+ }
}
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.math.BigInteger;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.net.util.SubnetUtils;
import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.opendaylight.controller.liblldp.EtherTypes;
-import org.opendaylight.controller.liblldp.HexEncode;
import org.opendaylight.controller.liblldp.NetUtils;
import org.opendaylight.controller.liblldp.PacketException;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.vpnservice.dhcpservice.api.DHCPConstants;
import org.opendaylight.vpnservice.dhcpservice.api.DHCPMConstants;
import org.opendaylight.vpnservice.dhcpservice.api.DHCPUtils;
-import org.opendaylight.vpnservice.mdsalutil.MDSALDataStoreUtils;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
import org.opendaylight.vpnservice.mdsalutil.packet.Ethernet;
+import org.opendaylight.vpnservice.mdsalutil.packet.IEEE8021Q;
import org.opendaylight.vpnservice.mdsalutil.packet.IPProtocols;
import org.opendaylight.vpnservice.mdsalutil.packet.IPv4;
import org.opendaylight.vpnservice.mdsalutil.packet.UDP;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnet.attributes.HostRoutes;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketInReason;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingListener;
import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketReceived;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingListener;
import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.SendToController;
import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetEgressActionsForInterfaceInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetEgressActionsForInterfaceOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetInterfaceFromIfIndexInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetInterfaceFromIfIndexInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.GetInterfaceFromIfIndexOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import com.google.common.base.Optional;
public class DhcpPktHandler implements AutoCloseable, PacketProcessingListener {
-
+
private static final Logger LOG = LoggerFactory.getLogger(DhcpPktHandler.class);
private final DataBroker dataBroker;
private final DhcpManager dhcpMgr;
-
+ private OdlInterfaceRpcService interfaceManagerRpc;
+ private static HashMap<String, ImmutablePair<BigInteger, String>> localCache = new HashMap<String, ImmutablePair<BigInteger, String>>();
private boolean computeUdpChecksum = true;
private PacketProcessingService pktService;
LOG.trace("Pkt received: {}", packet);
Class<? extends PacketInReason> pktInReason = packet.getPacketInReason();
short tableId = packet.getTableId().getValue();
- if (isPktInReasonSendtoCtrl(pktInReason) && ((DHCPMConstants.DHCP_TABLE == tableId))) {
+ if (isPktInReasonSendtoCtrl(pktInReason) && ((NwConstants.DHCP_TABLE == tableId))) {
byte[] inPayload = packet.getPayload();
Ethernet ethPkt = new Ethernet();
try {
return;
}
try {
- DHCP pktIn = getDhcpPktIn(ethPkt);
- LOG.trace("DHCPPkt received: {}", pktIn);
+ DHCP pktIn;
+ pktIn = getDhcpPktIn(ethPkt);
if (pktIn != null) {
- NodeConnectorRef inNcRef = packet.getIngress();
- FlowCapableNodeConnector fcNc = this.getFlowCapableNodeConnector(inNcRef);
- DHCP replyPkt = handleDhcpPacket(pktIn, fcNc);
- byte[] pktOut = getDhcpPacketOut(replyPkt, ethPkt, fcNc);
- sendPacketOut(pktOut, inNcRef);
+ LOG.trace("DHCPPkt received: {}", pktIn);
+ BigInteger metadata = packet.getMatch().getMetadata().getMetadata();
+ long portTag = MetaDataUtil.getLportFromMetadata(metadata).intValue();
+ String interfaceName = getInterfaceNameFromTag(portTag);
+ ImmutablePair<BigInteger, String> pair = getDpnIdPhysicalAddressFromInterfaceName(interfaceName);
+ DHCP replyPkt = handleDhcpPacket(pktIn, interfaceName);
+ byte[] pktOut = getDhcpPacketOut(replyPkt, ethPkt, pair.getRight());
+ sendPacketOut(pktOut, pair.getLeft(), interfaceName);
}
} catch (Exception e) {
- LOG.warn("Failed to get DHCP Reply", e);
+ LOG.warn("Failed to get DHCP Reply {}", e);
}
}
}
- private void sendPacketOut(byte[] pktOut, NodeConnectorRef ingress) {
- // We go out the same port we came in on
- InstanceIdentifier<Node> egressNodePath = getNodePath(ingress.getValue());
- TransmitPacketInput input = new TransmitPacketInputBuilder()
- .setPayload(pktOut).setNode(new NodeRef(egressNodePath))
- .setEgress(ingress).build();
- LOG.trace("Transmitting packet: {}",input);
- this.pktService.transmitPacket(input);
- }
-
- private InstanceIdentifier<Node> getNodePath(InstanceIdentifier<?> nodeInstanceId) {
- return nodeInstanceId.firstIdentifierOf(Node.class);
+ private void sendPacketOut(byte[] pktOut, BigInteger dpnId, String interfaceName) {
+ LOG.trace("Sending packet out DpId {}, portId {}, vlanId {}, interfaceName {}", dpnId, interfaceName);
+ List<Action> action = getEgressAction(interfaceName);
+ TransmitPacketInput output = MDSALUtil.getPacketOut(action, pktOut, dpnId);
+ LOG.trace("Transmitting packet: {}",output);
+ this.pktService.transmitPacket(output);
}
- private DHCP handleDhcpPacket(DHCP dhcpPkt, FlowCapableNodeConnector fcNc) {
+ private DHCP handleDhcpPacket(DHCP dhcpPkt, String interfaceName) {
LOG.debug("DHCP pkt rcvd {}", dhcpPkt);
byte msgType = dhcpPkt.getMsgType();
if (msgType == DHCPConstants.MSG_DECLINE) {
return null;
}
- Port nPort = getNeutronPort(fcNc);
+ Port nPort = getNeutronPort(interfaceName);
Subnet nSubnet = getNeutronSubnet(nPort);
DhcpInfo dhcpInfo = getDhcpInfo(nPort, nSubnet);
LOG.trace("NeutronPort: {} \n NeutronSubnet: {}, dhcpInfo{}",nPort, nSubnet, dhcpInfo);
return dhcpMgr.getNeutronSubnet(nPort);
}
- private Port getNeutronPort(FlowCapableNodeConnector fcNc) {
- return dhcpMgr.getNeutronPort(fcNc.getName());
+ private Port getNeutronPort(String interfaceName) {
+ return dhcpMgr.getNeutronPort(interfaceName);
}
- private FlowCapableNodeConnector getFlowCapableNodeConnector(NodeConnectorRef inNcRef) {
- InstanceIdentifier<NodeConnector> ncId = inNcRef.getValue().firstIdentifierOf(NodeConnector.class);
- Optional<NodeConnector> nodeConnector =
- MDSALDataStoreUtils.read(dataBroker, LogicalDatastoreType.OPERATIONAL, ncId);
- if(nodeConnector.isPresent()) {
- NodeConnector nc = nodeConnector.get();
- LOG.trace("Incoming pkt's NodeConnector: {}", nc);
- FlowCapableNodeConnector fcnc = nc.getAugmentation(FlowCapableNodeConnector.class);
- return fcnc;
+ private DHCP getDhcpPktIn(Ethernet actualEthernetPacket) {
+ Ethernet ethPkt = actualEthernetPacket;
+ LOG.trace("Inside getDhcpPktIn ethPkt {} \n getPayload {}", ethPkt, ethPkt.getPayload());
+ if (ethPkt.getEtherType() == (short)NwConstants.ETHTYPE_802_1Q) {
+ ethPkt = (Ethernet)ethPkt.getPayload();
}
- return null;
- }
-
- private DHCP getDhcpPktIn(Ethernet ethPkt) {
if (ethPkt.getPayload() instanceof IPv4) {
IPv4 ipPkt = (IPv4) ethPkt.getPayload();
if (ipPkt.getPayload() instanceof UDP) {
UDP udpPkt = (UDP) ipPkt.getPayload();
if ((udpPkt.getSourcePort() == DHCPMConstants.dhcpClientPort)
&& (udpPkt.getDestinationPort() == DHCPMConstants.dhcpServerPort)) {
+ LOG.trace("Matched dhcpClientPort and dhcpServerPort");
byte[] rawDhcpPayload = udpPkt.getRawPayload();
DHCP reply = new DHCP();
try {
reply.deserialize(rawDhcpPayload, 0, rawDhcpPayload.length);
} catch (PacketException e) {
- LOG.warn("Failed to deserialize DHCP pkt", e);
+ LOG.warn("Failed to deserialize DHCP pkt {}", e);
return null;
}
return reply;
return reply;
}
- protected byte[] getDhcpPacketOut(DHCP reply, Ethernet etherPkt, FlowCapableNodeConnector fcNc) {
+ protected byte[] getDhcpPacketOut(DHCP reply, Ethernet etherPkt, String phyAddrees) {
if (reply == null) {
/*
* DECLINE or RELEASE don't result in reply packet
ip4Reply.setTtl((byte) 32);
// create Ethernet Frame
Ethernet ether = new Ethernet();
+ if (etherPkt.getEtherType() == (short)NwConstants.ETHTYPE_802_1Q) {
+ IEEE8021Q vlanPacket = (IEEE8021Q) etherPkt.getPayload();
+ IEEE8021Q vlanTagged = new IEEE8021Q();
+ vlanTagged.setCFI(vlanPacket.getCfi());
+ vlanTagged.setPriority(vlanPacket.getPriority());
+ vlanTagged.setVlanId(vlanPacket.getVlanId());
+ vlanTagged.setPayload(ip4Reply);
+ vlanTagged.setEtherType(EtherTypes.IPv4.shortValue());
+ ether.setPayload(vlanTagged);
+ ether.setEtherType((short) NwConstants.ETHTYPE_802_1Q);
+ } else {
+ ether.setEtherType(EtherTypes.IPv4.shortValue());
+ ether.setPayload(ip4Reply);
+ }
//TODO:
- ether.setSourceMACAddress(getServerMacAddress(fcNc));
+ ether.setSourceMACAddress(getServerMacAddress(phyAddrees));
ether.setDestinationMACAddress(etherPkt.getSourceMACAddress());
- ether.setEtherType(EtherTypes.IPv4.shortValue());
- ether.setPayload(ip4Reply);
+
try {
rawPkt = ether.serialize();
} catch (PacketException e) {
return rawPkt;
}
- private byte[] getServerMacAddress(FlowCapableNodeConnector fcNc) {
+ private byte[] getServerMacAddress(String phyAddress) {
// Should we return ControllerMac instead?
- MacAddress macAddress = fcNc.getHardwareAddress();
- return DHCPUtils.strMacAddrtoByteArray(macAddress.getValue());
+ return DHCPUtils.strMacAddrtoByteArray(phyAddress);
}
public short computeChecksum(byte[] inData, byte[] srcAddr, byte[] destAddr) {
this.pktService = packetService;
}
+ public void setInterfaceManagerRpc(OdlInterfaceRpcService interfaceManagerRpc) {
+ LOG.trace("Registered interfaceManager successfully");;
+ this.interfaceManagerRpc = interfaceManagerRpc;
+ }
+
+ private String getInterfaceNameFromTag(long portTag) {
+ String interfaceName = null;
+ GetInterfaceFromIfIndexInput input = new GetInterfaceFromIfIndexInputBuilder().setIfIndex(new Integer((int)portTag)).build();
+ Future<RpcResult<GetInterfaceFromIfIndexOutput>> futureOutput = interfaceManagerRpc.getInterfaceFromIfIndex(input);
+ try {
+ GetInterfaceFromIfIndexOutput output = futureOutput.get().getResult();
+ interfaceName = output.getInterfaceName();
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.error("Error while retrieving the interfaceName from tag using getInterfaceFromIfIndex RPC");
+ }
+ LOG.trace("Returning interfaceName {} for tag {} form getInterfaceNameFromTag", interfaceName, portTag);
+ return interfaceName;
+ }
+
+ private org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface getInterfaceStateFromOperDS(String interfaceName) {
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId =
+ buildStateInterfaceId(interfaceName);
+ Optional<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateOptional =
+ MDSALUtil.read(LogicalDatastoreType.OPERATIONAL, ifStateId, dataBroker);
+ if (!ifStateOptional.isPresent()) {
+ return null;
+ }
+
+ return ifStateOptional.get();
+ }
+
+ private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> buildStateInterfaceId(String interfaceName) {
+ InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> idBuilder =
+ InstanceIdentifier.builder(InterfacesState.class)
+ .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class,
+ new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceKey(interfaceName));
+ InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> id = idBuilder.build();
+ return id;
+ }
+
+ private List<Action> getEgressAction(String interfaceName) {
+ List<Action> actions = null;
+ try {
+ Future<RpcResult<GetEgressActionsForInterfaceOutput>> result =
+ interfaceManagerRpc.getEgressActionsForInterface(
+ new GetEgressActionsForInterfaceInputBuilder().setIntfName(interfaceName).build());
+ RpcResult<GetEgressActionsForInterfaceOutput> rpcResult = result.get();
+ if(!rpcResult.isSuccessful()) {
+ LOG.warn("RPC Call to Get egress actions for interface {} returned with Errors {}", interfaceName, rpcResult.getErrors());
+ } else {
+ actions = rpcResult.getResult().getAction();
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ LOG.warn("Exception when egress actions for interface {}", interfaceName, e);
+ }
+ return actions;
+ }
+
+ private ImmutablePair<BigInteger, String> getDpnIdPhysicalAddressFromInterfaceName(String interfaceName) {
+ ImmutablePair<BigInteger, String> pair = localCache.get(interfaceName);
+ if (pair!=null && pair.getLeft() != null && pair.getRight() != null) {
+ return pair;
+ }
+ NodeConnectorId nodeConnectorId = null;
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState = getInterfaceStateFromOperDS(interfaceName);
+ if(interfaceState != null) {
+ List<String> ofportIds = interfaceState.getLowerLayerIf();
+ nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
+ }
+ BigInteger dpId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId));
+ String phyAddress = interfaceState==null ? "":interfaceState.getPhysAddress().getValue();
+ pair = new ImmutablePair<BigInteger, String>(dpId, phyAddress);
+ localCache.put(interfaceName, pair);
+ return null;
+ }
}
package org.opendaylight.vpnservice.dhcpservice;
import org.opendaylight.vpnservice.neutronvpn.interfaces.INeutronVpnManager;
-
import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
private NodeListener dhcpNodeListener;
private INeutronVpnManager neutronVpnManager;
private DhcpConfigListener dhcpConfigListener;
+ private OdlInterfaceRpcService interfaceManagerRpc;
+ private DhcpInterfaceEventListener dhcpInterfaceEventListener;
@Override
public void onSessionInitiated(ProviderContext session) {
dhcpManager.setNeutronVpnService(neutronVpnManager);
dhcpPktHandler = new DhcpPktHandler(dataBroker, dhcpManager);
dhcpPktHandler.setPacketProcessingService(pktProcessingService);
+ dhcpPktHandler.setInterfaceManagerRpc(interfaceManagerRpc);
packetListener = notificationService.registerNotificationListener(dhcpPktHandler);
dhcpNodeListener = new NodeListener(dataBroker, dhcpManager);
dhcpConfigListener = new DhcpConfigListener(dataBroker, dhcpManager);
+ dhcpInterfaceEventListener = new DhcpInterfaceEventListener(dhcpManager, dataBroker);
} catch (Exception e) {
- LOG.error("Error initializing services", e);
+ LOG.error("Error initializing services {}", e);
}
}
this.notificationService = notificationServiceDependency;
}
+ public void setInterfaceManagerRpc(OdlInterfaceRpcService interfaceManagerRpc) {
+ this.interfaceManagerRpc = interfaceManagerRpc;
+ }
}
return;
}
BigInteger dpId = new BigInteger(node[1]);
- dhcpManager.installDhcpEntries(dpId);
+ dhcpManager.setupTableMissForDhcpTable(dpId);
}
@Override
package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.impl.rev150710;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
import org.opendaylight.vpnservice.dhcpservice.DhcpProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
public class DhcpServiceImplModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.impl.rev150710.AbstractDhcpServiceImplModule {
public DhcpServiceImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
@Override
public java.lang.AutoCloseable createInstance() {
+ RpcProviderRegistry rpcregistryDependency = getRpcregistryDependency();
DhcpProvider dhcpProvider = new DhcpProvider();
dhcpProvider.setNotificationProviderService(getNotificationServiceDependency());
dhcpProvider.setMdsalManager(getMdsalutilDependency());
dhcpProvider.setNeutronVpnManager(getNeutronvpnDependency());
+ dhcpProvider.setInterfaceManagerRpc(rpcregistryDependency.getRpcService(OdlInterfaceRpcService.class));
getBrokerDependency().registerProvider(dhcpProvider);
return dhcpProvider;
}
public static final BigInteger COOKIE_VM_LFIB_TABLE = new BigInteger("8000002", 16);
public static final String TUNNEL_TABLE_FLOWID_PREFIX = "TUNNEL.";
public static final BigInteger TUNNEL_TABLE_COOKIE = new BigInteger("9000000", 16);
+ public static final short DEFAULT_SERVICE_INDEX = 0;
+ public static final int FLOW_HIGH_PRIORITY = 10;
+ public static final int FLOW_PRIORITY_FOR_UNTAGGED_VLAN = 4;
+ public static final BigInteger VLAN_TABLE_COOKIE = new BigInteger("8000000", 16);
}
import com.google.common.base.Optional;
import com.google.common.util.concurrent.ListenableFuture;
+
import org.eclipse.xtend.lib.annotations.Data;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
import org.opendaylight.vpnservice.interfacemgr.globals.InterfaceInfo;
import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.utilities.SouthboundUtils;
+import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
+import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
import org.opendaylight.vpnservice.mdsalutil.NwConstants;
import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddressBuilder;
}
updateStateEntry(interfaceNew, transaction, ifState);
+ NodeConnectorId nodeConnectorId = new NodeConnectorId(ifState.getLowerLayerIf().get(0));
+ BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+ long portNo = Long.valueOf(IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId));
+ Integer ifIndex = IfmUtil.allocateId(idManager, IfmConstants.IFM_IDPOOL_NAME, interfaceNew.getName());
IfL2vlan ifL2vlan = interfaceNew.getAugmentation(IfL2vlan.class);
- if (ifL2vlan == null || ifL2vlan.getL2vlanMode() != IfL2vlan.L2vlanMode.Trunk) {
+ if (ifL2vlan == null) {
+ futures.add(transaction.submit());
+ return;
+ }
+ if(interfaceNew.isEnabled() && ifState.getOperStatus() == OperStatus.Up) {
+ List<MatchInfo> matches = FlowBasedServicesUtils.getMatchInfoForVlanPortAtIngressTable(dpId, portNo, interfaceNew);
+ FlowBasedServicesUtils.installVlanFlow(dpId, portNo, interfaceNew, transaction, matches, ifIndex);
+ }
+ if (ifL2vlan.getL2vlanMode() != IfL2vlan.L2vlanMode.Trunk) {
+ futures.add(transaction.submit());
return;
}
InterfaceParentEntry interfaceParentEntry =
InterfaceMetaUtils.getInterfaceParentEntryFromConfigDS(interfaceParentEntryKey, dataBroker);
if (interfaceParentEntry == null) {
+ futures.add(transaction.submit());
return;
}
OperStatus operStatus = ifState.getOperStatus();
PhysAddress physAddress = ifState.getPhysAddress();
AdminStatus adminStatus = ifState.getAdminStatus();
- NodeConnectorId nodeConnectorId = new NodeConnectorId(ifState.getLowerLayerIf().get(0));
//FIXME: If the no. of child entries exceeds 100, perform txn updates in batches of 100.
for (InterfaceChildEntry interfaceChildEntry : interfaceChildEntries) {
List<String> childLowerLayerIfList = new ArrayList<>();
childLowerLayerIfList.add(0, nodeConnectorId.getValue());
childLowerLayerIfList.add(1, interfaceNew.getName());
+ ifIndex = IfmUtil.allocateId(idManager, IfmConstants.IFM_IDPOOL_NAME, ifaceChild.getName());
InterfaceBuilder childIfaceBuilder = new InterfaceBuilder().setAdminStatus(adminStatus)
.setOperStatus(operStatus).setPhysAddress(physAddress).setLowerLayerIf(childLowerLayerIfList);
childIfaceBuilder.setKey(IfmUtil.getStateInterfaceKeyFromName(ifaceChild.getName()));
transaction.put(LogicalDatastoreType.OPERATIONAL, ifChildStateId, childIfaceBuilder.build(), true);
+ if (operStatus == OperStatus.Up) {
+ List<MatchInfo> matches = FlowBasedServicesUtils.getMatchInfoForVlanPortAtIngressTable(dpId, portNo, ifaceChild);
+ FlowBasedServicesUtils.installVlanFlow(dpId, portNo, ifaceChild, transaction, matches, ifIndex);
+ }
}
futures.add(transaction.submit());
}
package org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers;
import com.google.common.util.concurrent.ListenableFuture;
+
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
import org.opendaylight.vpnservice.interfacemgr.renderer.ovs.utilities.SouthboundUtils;
+import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
import org.opendaylight.vpnservice.mdsalutil.NwConstants;
import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
}
}
IfL2vlan ifL2vlan = interfaceOld.getAugmentation(IfL2vlan.class);
- if (ifL2vlan == null || ifL2vlan.getL2vlanMode() != IfL2vlan.L2vlanMode.Trunk) {
+ if (ifL2vlan == null) {
+ return;
+ }
+ BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+ FlowBasedServicesUtils.removeIngressFlow(interfaceOld, dpId, t);
+ if (ifL2vlan.getL2vlanMode() != IfL2vlan.L2vlanMode.Trunk) {
return;
}
InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifChildStateId =
IfmUtil.buildStateInterfaceId(interfaceChildEntry.getChildInterface());
t.delete(LogicalDatastoreType.OPERATIONAL, ifChildStateId);
+ InterfaceKey childIfKey = new InterfaceKey(interfaceChildEntry.getChildInterface());
+ FlowBasedServicesUtils.removeIngressFlow(InterfaceManagerCommonUtils.getInterfaceFromConfigDS(childIfKey, dataBroker), dpId, t);
}
}
package org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers;
import com.google.common.util.concurrent.ListenableFuture;
+
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
+import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
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.interfaces.rev140508.interfaces.state.Interface.AdminStatus;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.InterfaceBuilder;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
// create lportTag Interface Map
InterfaceMetaUtils.createLportTagInterfaceMap(t, interfaceNew.getName(), ifIndex);
+ //Installing vlan flow for vlan member
+ NodeConnectorId nodeConnectorId = new NodeConnectorId(ifState.getLowerLayerIf().get(0));
+ BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+ long portNo = Long.valueOf(IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId));
+ if (operStatus == OperStatus.Up) {
+ List<MatchInfo> matches = FlowBasedServicesUtils.getMatchInfoForVlanPortAtIngressTable(dpId, portNo, interfaceNew);
+ FlowBasedServicesUtils.installVlanFlow(dpId, portNo, interfaceNew, t, matches, ifIndex);
+ }
// FIXME: Maybe, add the new interface to the higher-layer if of the parent interface-state.
// That may not serve any purpose though for interface manager.... Unless some external parties are interested in it.
*/
package org.opendaylight.vpnservice.interfacemgr.renderer.ovs.confighelpers;
-import com.google.common.util.concurrent.ListenableFuture;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.idmanager.IdManager;
import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.ArrayList;
-import java.util.List;
+import com.google.common.util.concurrent.ListenableFuture;
public class OvsVlanMemberConfigRemoveHelper {
private static final Logger LOG = LoggerFactory.getLogger(OvsVlanMemberConfigRemoveHelper.class);
}
} */
+ String ncStr = ifState.getLowerLayerIf().get(0);
+ NodeConnectorId nodeConnectorId = new NodeConnectorId(ncStr);
+ BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifStateId =
IfmUtil.buildStateInterfaceId(interfaceOld.getName());
t.delete(LogicalDatastoreType.OPERATIONAL, ifStateId);
+ FlowBasedServicesUtils.removeIngressFlow(interfaceOld, dpId, t);
}
futures.add(t.submit());
return futures;
}
+ BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+ long portNo = Long.valueOf(IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId));
// If this interface is a tunnel interface, create the tunnel ingress flow
IfTunnel tunnel = iface.getAugmentation(IfTunnel.class);
if(tunnel != null){
- BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
- long portNo = Long.valueOf(IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId));
InterfaceManagerCommonUtils.makeTunnelIngressFlow(futures, mdsalApiManager, tunnel,dpId, portNo, iface,
ifIndex, NwConstants.ADD_FLOW);
futures.add(transaction.submit());
// If this interface maps to a Vlan trunk entity, operational states of all the vlan-trunk-members
// should also be created here.
IfL2vlan ifL2vlan = iface.getAugmentation(IfL2vlan.class);
- if (ifL2vlan == null || ifL2vlan.getL2vlanMode() != IfL2vlan.L2vlanMode.Trunk) {
+ if (ifL2vlan == null) {
+ futures.add(transaction.submit());
+ return futures;
+ }
+ if(operStatus == Interface.OperStatus.Up) {
+ List<MatchInfo> matches = FlowBasedServicesUtils.getMatchInfoForVlanPortAtIngressTable(dpId, portNo, iface);
+ FlowBasedServicesUtils.installVlanFlow(dpId, portNo, iface, transaction, matches, ifIndex);
+ }
+ if (ifL2vlan.getL2vlanMode() != IfL2vlan.L2vlanMode.Trunk) {
futures.add(transaction.submit());
return futures;
}
-
InterfaceParentEntryKey interfaceParentEntryKey = new InterfaceParentEntryKey(iface.getName());
InterfaceParentEntry interfaceParentEntry =
InterfaceMetaUtils.getInterfaceParentEntryFromConfigDS(interfaceParentEntryKey, dataBroker);
if (!ifaceChild.isEnabled()) {
operStatus = Interface.OperStatus.Down;
}
-
InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> ifChildStateId =
IfmUtil.buildStateInterfaceId(ifaceChild.getName());
List<String> childLowerLayerIfList = new ArrayList<>();
// create lportTag Interface Map
InterfaceMetaUtils.createLportTagInterfaceMap(transaction, ifaceChild.getName(), ifIndex);
+ if (operStatus == Interface.OperStatus.Up) {
+ List<MatchInfo> matches = FlowBasedServicesUtils.getMatchInfoForVlanPortAtIngressTable(dpId, portNo, ifaceChild);
+ FlowBasedServicesUtils.installVlanFlow(dpId, portNo, ifaceChild, transaction, matches, ifIndex);
+ }
}
/** Below code will be needed if we want to update the vlan-trunks on the of-port
package org.opendaylight.vpnservice.interfacemgr.renderer.ovs.statehelpers;
import com.google.common.util.concurrent.ListenableFuture;
+
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.vpnservice.interfacemgr.commons.AlivenessMonitorUtils;
import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
+import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
import org.opendaylight.vpnservice.mdsalutil.NwConstants;
import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
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.interfaces.rev140508.interfaces.state.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntry;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info.InterfaceParentEntryKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007._interface.child.info._interface.parent.entry.InterfaceChildEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfTunnel;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
return futures;
}
+ NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
+ BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
// If this interface is a tunnel interface, remove the tunnel ingress flow and stop lldp monitoring
IfTunnel tunnel = iface.getAugmentation(IfTunnel.class);
if(tunnel != null){
- NodeConnectorId nodeConnectorId = InstanceIdentifier.keyOf(key.firstIdentifierOf(NodeConnector.class)).getId();
- BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
long portNo = Long.valueOf(IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId));
InterfaceManagerCommonUtils.makeTunnelIngressFlow(futures, mdsalApiManager, tunnel, dpId, portNo, iface, -1,
NwConstants.DEL_FLOW);
return futures;
}
+ IfL2vlan ifL2vlan = iface.getAugmentation(IfL2vlan.class);
+ if (ifL2vlan == null) {
+ futures.add(transaction.submit());
+ return futures;
+ }
+ FlowBasedServicesUtils.removeIngressFlow(iface, dpId, transaction);
+ if (ifL2vlan.getL2vlanMode() != IfL2vlan.L2vlanMode.Trunk) {
+ futures.add(transaction.submit());
+ return futures;
+ }
+
InterfaceParentEntryKey interfaceParentEntryKey = new InterfaceParentEntryKey(iface.getName());
InterfaceParentEntry interfaceParentEntry =
InterfaceMetaUtils.getInterfaceParentEntryFromConfigDS(interfaceParentEntryKey, dataBroker);
if(interfaceState != null) {
InterfaceMetaUtils.removeLportTagInterfaceMap(transaction, idManager, dataBroker, childInterfaceState.getName(), childInterfaceState.getIfIndex());
transaction.delete(LogicalDatastoreType.OPERATIONAL, ifChildStateId);
+ InterfaceKey childIfKey = new InterfaceKey(interfaceChildEntry.getChildInterface());
+ FlowBasedServicesUtils.removeIngressFlow(InterfaceManagerCommonUtils.getInterfaceFromConfigDS(childIfKey, dataBroker), dpId, transaction);
}
}
if(L2vlan.class.equals(ifType)){
IfL2vlan vlanIface = interfaceInfo.getAugmentation(IfL2vlan.class);
LOG.trace("L2Vlan: {}",vlanIface);
- long vlanVid = (vlanIface == null) ? 0 : vlanIface.getVlanId().getValue();
- if (vlanVid != 0) {
+ long vlanVid = 0;
+ boolean isVlanTransparent = false;
+ if (vlanIface != null) {
+ vlanVid = vlanIface.getVlanId() == null ? 0 : vlanIface.getVlanId().getValue();
+ isVlanTransparent = vlanIface.getL2vlanMode() == IfL2vlan.L2vlanMode.Transparent;
+ }
+ if (vlanVid != 0 && !isVlanTransparent) {
listActionInfo.add(new ActionInfo(ActionType.push_vlan, new String[] {}));
listActionInfo.add(new ActionInfo(ActionType.set_field_vlan_vid,
new String[] { Long.toString(vlanVid) }));
*/
package org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.confighelpers;
-import com.google.common.util.concurrent.ListenableFuture;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.ServicesInfo;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.services.info.BoundServices;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
+import com.google.common.util.concurrent.ListenableFuture;
public class FlowBasedServicesConfigBindHelper {
private static final Logger LOG = LoggerFactory.getLogger(FlowBasedServicesConfigBindHelper.class);
public static List<ListenableFuture<Void>> bindService(InstanceIdentifier<BoundServices> instanceIdentifier,
BoundServices boundServiceNew, DataBroker dataBroker) {
List<ListenableFuture<Void>> futures = new ArrayList<>();
- WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
String interfaceName =
InstanceIdentifier.keyOf(instanceIdentifier.firstIdentifierOf(ServicesInfo.class)).getInterfaceName();
return futures;
}
+ // Split based on type of interface....
+ if (iface.getType().isAssignableFrom(L2vlan.class)) {
+ return bindServiceOnVlan(boundServiceNew, allServices, iface, ifState.getIfIndex(), dataBroker);
+ } else if (iface.getType().isAssignableFrom(Tunnel.class)) {
+ return bindServiceOnTunnel(boundServiceNew, allServices, iface, ifState.getIfIndex(), dataBroker);
+ }
+ return futures;
+ }
+
+ private static List<ListenableFuture<Void>> bindServiceOnTunnel(BoundServices boundServiceNew, List<BoundServices> allServices, Interface iface, int ifIndex, DataBroker dataBroker) {
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
NodeConnectorId nodeConnectorId = FlowBasedServicesUtils.getNodeConnectorIdFromInterface(iface, dataBroker);
long portNo = Long.parseLong(IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId));
BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+ WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
if (allServices.size() == 1) {
// If only one service present, install instructions in table 0.
- int vlanId = 0;
List<MatchInfo> matches = null;
- if (iface.getType().isAssignableFrom(L2vlan.class)) {
- matches = FlowBasedServicesUtils.getMatchInfoForVlanPortAtIngressTable(dpId, portNo, iface);
- } else if (iface.getType().isAssignableFrom(Tunnel.class)){
- matches = FlowBasedServicesUtils.getMatchInfoForTunnelPortAtIngressTable (dpId, portNo, iface);
- }
-
- if (matches != null) {
- FlowBasedServicesUtils.installInterfaceIngressFlow(dpId, iface, boundServiceNew,
- transaction, matches, ifState.getIfIndex(), NwConstants.VLAN_INTERFACE_INGRESS_TABLE);
- }
-
+ matches = FlowBasedServicesUtils.getMatchInfoForTunnelPortAtIngressTable (dpId, portNo, iface);
+ FlowBasedServicesUtils.installInterfaceIngressFlow(dpId, iface, boundServiceNew,
+ transaction, matches, ifIndex, NwConstants.VLAN_INTERFACE_INGRESS_TABLE);
if (transaction != null) {
futures.add(transaction.submit());
}
if (!isCurrentServiceHighestPriority) {
FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, boundServiceNew, iface, transaction,
- ifState.getIfIndex());
+ ifIndex, boundServiceNew.getServicePriority(), (short) (boundServiceNew.getServicePriority()+1));
} else {
BoundServices serviceToReplace = tmpServicesMap.get(highestPriority);
FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, serviceToReplace, iface, transaction,
- ifState.getIfIndex());
+ ifIndex, boundServiceNew.getServicePriority(), (short) (boundServiceNew.getServicePriority()+1));
List<MatchInfo> matches = null;
- if (iface.getType().isAssignableFrom(L2vlan.class)) {
- matches = FlowBasedServicesUtils.getMatchInfoForVlanPortAtIngressTable(dpId, portNo, iface);
- } else if (iface.getType().isAssignableFrom(Tunnel.class)){
- matches = FlowBasedServicesUtils.getMatchInfoForTunnelPortAtIngressTable (dpId, portNo, iface);
- }
+ matches = FlowBasedServicesUtils.getMatchInfoForTunnelPortAtIngressTable (dpId, portNo, iface);
if (matches != null) {
WriteTransaction installFlowTransaction = dataBroker.newWriteOnlyTransaction();
FlowBasedServicesUtils.installInterfaceIngressFlow(dpId, iface, boundServiceNew, installFlowTransaction,
- matches, ifState.getIfIndex(), NwConstants.VLAN_INTERFACE_INGRESS_TABLE);
+ matches, ifIndex, NwConstants.VLAN_INTERFACE_INGRESS_TABLE);
futures.add(installFlowTransaction.submit());
}
}
}
return futures;
}
+
+ private static List<ListenableFuture<Void>> bindServiceOnVlan(BoundServices boundServiceNew, List<BoundServices> allServices, Interface iface, int ifIndex, DataBroker dataBroker) {
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ NodeConnectorId nodeConnectorId = FlowBasedServicesUtils.getNodeConnectorIdFromInterface(iface, dataBroker);
+ BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+ WriteTransaction transaction = dataBroker.newWriteOnlyTransaction();
+
+ if (allServices.size() == 1) {
+ //calling LportDispatcherTableForService with current service index as 0 and next service index as some value since this is the only service bound.
+ FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, boundServiceNew, iface,
+ transaction, ifIndex, IfmConstants.DEFAULT_SERVICE_INDEX,(short) (boundServiceNew.getServicePriority() + 1));
+ if (transaction != null) {
+ futures.add(transaction.submit());
+ }
+ return futures;
+ }
+ allServices.remove(boundServiceNew);
+ BoundServices[] highLowPriorityService = FlowBasedServicesUtils.getHighAndLowPriorityService(allServices, boundServiceNew);
+ BoundServices low = highLowPriorityService[0];
+ BoundServices high = highLowPriorityService[1];
+ BoundServices highest = FlowBasedServicesUtils.getHighestPriorityService(allServices);
+ short currentServiceIndex = IfmConstants.DEFAULT_SERVICE_INDEX;
+ short nextServiceIndex = (short) (boundServiceNew.getServicePriority() + 1); // dummy service index
+ if (low != null) {
+ nextServiceIndex = low.getServicePriority();
+ if (low.equals(highest)) {
+ //In this case the match criteria of existing service should be changed.
+ BoundServices lower = FlowBasedServicesUtils.getHighAndLowPriorityService(allServices, low)[0];
+ short lowerServiceIndex = (short) ((lower!=null) ? lower.getServicePriority() : low.getServicePriority() + 1);
+ LOG.trace("Installing table 30 entry for existing service {} service match on service index {} update with service index {}", low, low.getServicePriority(), lowerServiceIndex);
+ FlowBasedServicesUtils.installLPortDispatcherFlow(dpId,low, iface, transaction, ifIndex,low.getServicePriority(), lowerServiceIndex);
+ } else {
+ currentServiceIndex = boundServiceNew.getServicePriority();
+ }
+ }
+ if (high != null) {
+ currentServiceIndex = boundServiceNew.getServicePriority();
+ if (high.equals(highest)) {
+ LOG.trace("Installing table 30 entry for existing service {} service match on service index {} update with service index {}", high, IfmConstants.DEFAULT_SERVICE_INDEX, currentServiceIndex);
+ FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, high, iface, transaction, ifIndex, IfmConstants.DEFAULT_SERVICE_INDEX, currentServiceIndex);
+ } else {
+ LOG.trace("Installing table 30 entry for existing service {} service match on service index {} update with service index {}", high, high.getServicePriority(), currentServiceIndex);
+ FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, high, iface, transaction, ifIndex, high.getServicePriority(), currentServiceIndex);
+ }
+ }
+ LOG.trace("Installing table 30 entry for new service match on service index {} update with service index {}", currentServiceIndex, nextServiceIndex);
+ FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, boundServiceNew, iface, transaction, ifIndex, currentServiceIndex, nextServiceIndex);
+ futures.add(transaction.submit());
+ return futures;
+ }
}
\ No newline at end of file
*/
package org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.confighelpers;
-import com.google.common.util.concurrent.ListenableFuture;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.ServicesInfo;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.services.info.BoundServices;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rev150331.IfL2vlan;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
+import com.google.common.util.concurrent.ListenableFuture;
public class FlowBasedServicesConfigUnbindHelper {
private static final Logger LOG = LoggerFactory.getLogger(FlowBasedServicesConfigUnbindHelper.class);
public static List<ListenableFuture<Void>> unbindService(InstanceIdentifier<BoundServices> instanceIdentifier,
BoundServices boundServiceOld, DataBroker dataBroker) {
List<ListenableFuture<Void>> futures = new ArrayList<>();
- WriteTransaction t = dataBroker.newWriteOnlyTransaction();
-
String interfaceName =
InstanceIdentifier.keyOf(instanceIdentifier.firstIdentifierOf(ServicesInfo.class)).getInterfaceName();
+
+ // Get the Parent ServiceInfo
+ ServicesInfo servicesInfo = FlowBasedServicesUtils.getServicesInfoForInterface(interfaceName, dataBroker);
+ if (servicesInfo == null) {
+ LOG.error("Reached Impossible part in the code for bound service: {}", boundServiceOld);
+ return futures;
+ }
+
+ InterfaceKey interfaceKey = new InterfaceKey(interfaceName);
+ Interface iface = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface ifState =
InterfaceManagerCommonUtils.getInterfaceStateFromOperDS(interfaceName, dataBroker);
if (ifState == null || ifState.getOperStatus() == OperStatus.Down) {
ifState.getOperStatus(), interfaceName);
return futures;
}
+ List<BoundServices> boundServices = servicesInfo.getBoundServices();
- // Get the Parent ServiceInfo
- ServicesInfo servicesInfo = FlowBasedServicesUtils.getServicesInfoForInterface(interfaceName, dataBroker);
- if (servicesInfo == null) {
- LOG.error("Reached Impossible part in the code for bound service: {}", boundServiceOld);
+ // Split based on type of interface....
+ if (iface.getType().isAssignableFrom(L2vlan.class)) {
+ return unbindServiceOnVlan(boundServiceOld, boundServices, iface, ifState.getIfIndex(), dataBroker);
+ } else if (iface.getType().isAssignableFrom(Tunnel.class)) {
+ return unbindServiceOnTunnel(boundServiceOld, boundServices, iface, ifState.getIfIndex(), dataBroker);
+ }
+ return futures;
+ }
+
+ private static List<ListenableFuture<Void>> unbindServiceOnVlan(
+ BoundServices boundServiceOld,
+ List<BoundServices> boundServices, Interface iface, int ifIndex,
+ DataBroker dataBroker) {
+
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+ NodeConnectorId nodeConnectorId = FlowBasedServicesUtils.getNodeConnectorIdFromInterface(iface, dataBroker);
+ BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+ if (boundServices.isEmpty()) {
+ // Remove default entry from Lport Dispatcher Table.
+ FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface, boundServiceOld, t, IfmConstants.DEFAULT_SERVICE_INDEX);
+ if (t != null) {
+ futures.add(t.submit());
+ }
return futures;
}
+ BoundServices[] highLow = FlowBasedServicesUtils.getHighAndLowPriorityService(boundServices, boundServiceOld);
+ BoundServices low = highLow[0];
+ BoundServices high = highLow[1];
+ // This means the one removed was the highest priority service
+ if (high == null) {
+ LOG.trace("Deleting table entry for service {}, match service index {}", boundServiceOld, IfmConstants.DEFAULT_SERVICE_INDEX);
+ FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface, boundServiceOld, t, IfmConstants.DEFAULT_SERVICE_INDEX);
+ if (low != null) {
+ //delete the lower services flow entry.
+ LOG.trace("Deleting table entry for lower service {}, match service index {}", low, low.getServicePriority());
+ FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface, low, t, low.getServicePriority());
+ BoundServices lower = FlowBasedServicesUtils.getHighAndLowPriorityService(boundServices, low)[0];
+ short lowerServiceIndex = (short) ((lower!=null) ? lower.getServicePriority() : low.getServicePriority() + 1);
+ LOG.trace("Installing new entry for lower service {}, match service index {}, update service index {}", low, IfmConstants.DEFAULT_SERVICE_INDEX, lowerServiceIndex);
+ FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, low, iface, t, ifIndex, IfmConstants.DEFAULT_SERVICE_INDEX, lowerServiceIndex);
+ }
+ } else {
+ LOG.trace("Deleting table entry for service {}, match service index {}", boundServiceOld, boundServiceOld.getServicePriority());
+ FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface, boundServiceOld, t, boundServiceOld.getServicePriority());
+ short lowerServiceIndex = (short) ((low!=null) ? low.getServicePriority() : boundServiceOld.getServicePriority() + 1);
+ BoundServices highest = FlowBasedServicesUtils.getHighestPriorityService(boundServices);
+ if (high.equals(highest)) {
+ LOG.trace("Update the existing higher service {}, match service index {}, update service index {}", high, IfmConstants.DEFAULT_SERVICE_INDEX, lowerServiceIndex);
+ FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, high, iface, t, ifIndex, IfmConstants.DEFAULT_SERVICE_INDEX, lowerServiceIndex);
+ } else {
+ LOG.trace("Update the existing higher service {}, match service index {}, update service index {}", high, high.getServicePriority(), lowerServiceIndex);
+ FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, high, iface, t, ifIndex, high.getServicePriority(), lowerServiceIndex);
+ }
+ }
+ futures.add(t.submit());
+ return futures;
+ }
- InterfaceKey interfaceKey = new InterfaceKey(interfaceName);
- Interface iface = InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
+ private static List<ListenableFuture<Void>> unbindServiceOnTunnel(
+ BoundServices boundServiceOld,
+ List<BoundServices> boundServices, Interface iface, int ifIndex,
+ DataBroker dataBroker) {
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+
+ WriteTransaction t = dataBroker.newWriteOnlyTransaction();
NodeConnectorId nodeConnectorId = FlowBasedServicesUtils.getNodeConnectorIdFromInterface(iface, dataBroker);
long portNo = Long.parseLong(IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId));
BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
- List<BoundServices> boundServices = servicesInfo.getBoundServices();
if (boundServices.isEmpty()) {
// Remove entry from Ingress Table.
FlowBasedServicesUtils.removeIngressFlow(iface, boundServiceOld, dpId, t);
}
if (highestPriority < boundServiceOld.getServicePriority()) {
- FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface, boundServiceOld, t);
+ FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface, boundServiceOld, t, boundServiceOld.getServicePriority());
if (t != null) {
futures.add(t.submit());
}
}
List<MatchInfo> matches = null;
- if (iface.getType().isAssignableFrom(L2vlan.class)) {
- matches = FlowBasedServicesUtils.getMatchInfoForVlanPortAtIngressTable(dpId, portNo, iface);
- } else if (iface.getType().isAssignableFrom(Tunnel.class)){
- matches = FlowBasedServicesUtils.getMatchInfoForTunnelPortAtIngressTable (dpId, portNo, iface);
- }
+ matches = FlowBasedServicesUtils.getMatchInfoForTunnelPortAtIngressTable (dpId, portNo, iface);
BoundServices toBeMoved = tmpServicesMap.get(highestPriority);
FlowBasedServicesUtils.removeIngressFlow(iface, boundServiceOld, dpId, t);
FlowBasedServicesUtils.installInterfaceIngressFlow(dpId, iface, toBeMoved, t,
- matches, ifState.getIfIndex(), NwConstants.VLAN_INTERFACE_INGRESS_TABLE);
- FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface, toBeMoved, t);
+ matches, ifIndex, NwConstants.VLAN_INTERFACE_INGRESS_TABLE);
+ FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface, toBeMoved, t, toBeMoved.getServicePriority());
if (t != null) {
futures.add(t.submit());
}
return futures;
}
+
}
\ No newline at end of file
package org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.statehelpers;
import com.google.common.util.concurrent.ListenableFuture;
+
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
import java.math.BigInteger;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
public class FlowBasedServicesStateBindHelper {
public static List<ListenableFuture<Void>> bindServicesOnInterface(Interface ifaceState,
DataBroker dataBroker) {
List<ListenableFuture<Void>> futures = new ArrayList<>();
- WriteTransaction t = dataBroker.newWriteOnlyTransaction();
ServicesInfo servicesInfo = FlowBasedServicesUtils.getServicesInfoForInterface(ifaceState.getName(), dataBroker);
if (servicesInfo == null) {
return futures;
return futures;
}
- BoundServices highestPriorityBoundService = null;
- short highestPriority = 0xFF;
- for (BoundServices boundService : allServices) {
- if (boundService.getServicePriority() < highestPriority) {
- highestPriorityBoundService = boundService;
- highestPriority = boundService.getServicePriority();
- }
- }
-
InterfaceKey interfaceKey = new InterfaceKey(ifaceState.getName());
org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
- NodeConnectorId nodeConnectorId = FlowBasedServicesUtils.getNodeConnectorIdFromInterface(iface, dataBroker);
- long portNo = Long.parseLong(IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId));
- BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
- List<MatchInfo> matches = null;
if (iface.getType().isAssignableFrom(L2vlan.class)) {
- matches = FlowBasedServicesUtils.getMatchInfoForVlanPortAtIngressTable(dpId, portNo, iface);
+ return bindServiceOnVlan(allServices, iface, ifaceState.getIfIndex(), dataBroker);
} else if (iface.getType().isAssignableFrom(Tunnel.class)){
- matches = FlowBasedServicesUtils.getMatchInfoForTunnelPortAtIngressTable (dpId, portNo, iface);
+ return bindServiceOnTunnel(allServices, iface, ifaceState.getIfIndex(), dataBroker);
}
+ return futures;
+ }
+ private static List<ListenableFuture<Void>> bindServiceOnTunnel(
+ List<BoundServices> allServices,
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface,
+ Integer ifIndex, DataBroker dataBroker) {
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ NodeConnectorId nodeConnectorId = FlowBasedServicesUtils.getNodeConnectorIdFromInterface(iface, dataBroker);
+ long portNo = Long.parseLong(IfmUtil.getPortNoFromNodeConnectorId(nodeConnectorId));
+ BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+ List<MatchInfo> matches = FlowBasedServicesUtils.getMatchInfoForTunnelPortAtIngressTable (dpId, portNo, iface);
+ BoundServices highestPriorityBoundService = FlowBasedServicesUtils.getHighestPriorityService(allServices);
+ WriteTransaction t = dataBroker.newWriteOnlyTransaction();
if (matches != null) {
FlowBasedServicesUtils.installInterfaceIngressFlow(dpId, iface, highestPriorityBoundService,
- t, matches, ifaceState.getIfIndex(), NwConstants.VLAN_INTERFACE_INGRESS_TABLE);
+ t, matches, ifIndex, NwConstants.VLAN_INTERFACE_INGRESS_TABLE);
}
for (BoundServices boundService : allServices) {
if (!boundService.equals(highestPriorityBoundService)) {
- FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, boundService, iface, t, ifaceState.getIfIndex());
+ FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, boundService, iface, t, ifIndex, boundService.getServicePriority(), (short) (boundService.getServicePriority()+1));
}
}
futures.add(t.submit());
return futures;
}
+
+ private static List<ListenableFuture<Void>> bindServiceOnVlan(
+ List<BoundServices> allServices,
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface,
+ Integer ifIndex, DataBroker dataBroker) {
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ NodeConnectorId nodeConnectorId = FlowBasedServicesUtils.getNodeConnectorIdFromInterface(iface, dataBroker);
+ BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+ WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+ Collections.sort(allServices, new Comparator<BoundServices>() {
+ @Override
+ public int compare(BoundServices serviceInfo1, BoundServices serviceInfo2) {
+ return serviceInfo2.getServicePriority().compareTo(serviceInfo1.getServicePriority());
+ }
+ });
+ BoundServices highestPriority = allServices.remove(0);
+ short nextServiceIndex = (short) (allServices.size() > 0 ? allServices.get(0).getServicePriority() : highestPriority.getServicePriority() + 1);
+ FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, highestPriority, iface, t, ifIndex, IfmConstants.DEFAULT_SERVICE_INDEX, nextServiceIndex);
+ BoundServices prev = null;
+ for (BoundServices boundService : allServices) {
+ if (prev!=null) {
+ FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, prev, iface, t, ifIndex, prev.getServicePriority(), boundService.getServicePriority());
+ }
+ prev = boundService;
+ }
+ if (prev!=null) {
+ FlowBasedServicesUtils.installLPortDispatcherFlow(dpId, prev, iface, t, ifIndex, prev.getServicePriority(), (short) (prev.getServicePriority()+1));
+ }
+ futures.add(t.submit());
+ return futures;
+
+ }
+
}
\ No newline at end of file
*/
package org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.statehelpers;
-import com.google.common.util.concurrent.ListenableFuture;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
import org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.utilities.FlowBasedServicesUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.L2vlan;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.Tunnel;
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.interfaces.rev140508.interfaces.state.Interface;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.List;
+import com.google.common.util.concurrent.ListenableFuture;
public class FlowBasedServicesStateUnbindHelper {
private static final Logger LOG = LoggerFactory.getLogger(FlowBasedServicesStateUnbindHelper.class);
public static List<ListenableFuture<Void>> unbindServicesFromInterface(Interface ifaceState,
DataBroker dataBroker) {
List<ListenableFuture<Void>> futures = new ArrayList<>();
- WriteTransaction t = dataBroker.newWriteOnlyTransaction();
ServicesInfo servicesInfo = FlowBasedServicesUtils.getServicesInfoForInterface(ifaceState.getName(), dataBroker);
if (servicesInfo == null) {
return futures;
}
- BoundServices highestPriorityBoundService = null;
- short highestPriority = 0xFF;
- for (BoundServices boundService : allServices) {
- if (boundService.getServicePriority() < highestPriority) {
- highestPriorityBoundService = boundService;
- highestPriority = boundService.getServicePriority();
- }
- }
-
InterfaceKey interfaceKey = new InterfaceKey(ifaceState.getName());
org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface =
- InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
+ InterfaceManagerCommonUtils.getInterfaceFromConfigDS(interfaceKey, dataBroker);
+
+ if (iface.getType().isAssignableFrom(L2vlan.class)) {
+ return unbindServiceOnVlan(allServices, iface, ifaceState.getIfIndex(), dataBroker);
+ } else if (iface.getType().isAssignableFrom(Tunnel.class)){
+ return unbindServiceOnTunnel(allServices, iface, ifaceState.getIfIndex(), dataBroker);
+ }
+ return futures;
+ }
+
+ private static List<ListenableFuture<Void>> unbindServiceOnTunnel(
+ List<BoundServices> allServices,
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface,
+ Integer ifIndex, DataBroker dataBroker) {
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ WriteTransaction t = dataBroker.newWriteOnlyTransaction();
NodeConnectorId nodeConnectorId = FlowBasedServicesUtils.getNodeConnectorIdFromInterface(iface, dataBroker);
if(nodeConnectorId == null){
return futures;
}
+ BoundServices highestPriorityBoundService = FlowBasedServicesUtils.getHighestPriorityService(allServices);
+
BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
FlowBasedServicesUtils.removeIngressFlow(iface, highestPriorityBoundService, dpId, t);
for (BoundServices boundService : allServices) {
if (!boundService.equals(highestPriorityBoundService)) {
- FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface, boundService, t);
+ FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface, boundService, t, boundService.getServicePriority());
}
}
+ futures.add(t.submit());
+ return futures;
+ }
+
+ private static List<ListenableFuture<Void>> unbindServiceOnVlan(
+ List<BoundServices> allServices,
+ org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface,
+ Integer ifIndex, DataBroker dataBroker) {
+ List<ListenableFuture<Void>> futures = new ArrayList<>();
+ WriteTransaction t = dataBroker.newWriteOnlyTransaction();
+ NodeConnectorId nodeConnectorId = FlowBasedServicesUtils.getNodeConnectorIdFromInterface(iface, dataBroker);
+ if (nodeConnectorId == null) {
+ return futures;
+ }
+ BigInteger dpId = new BigInteger(IfmUtil.getDpnFromNodeConnectorId(nodeConnectorId));
+ Collections.sort(allServices, new Comparator<BoundServices>() {
+ @Override
+ public int compare(BoundServices serviceInfo1, BoundServices serviceInfo2) {
+ return serviceInfo2.getServicePriority().compareTo(serviceInfo1.getServicePriority());
+ }
+ });
+ BoundServices highestPriority = allServices.remove(0);
+ FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface, highestPriority, t, IfmConstants.DEFAULT_SERVICE_INDEX);
+ for (BoundServices boundService : allServices) {
+ FlowBasedServicesUtils.removeLPortDispatcherFlow(dpId, iface, boundService, t, boundService.getServicePriority());
+ }
+ futures.add(t.submit());
return futures;
+
}
-}
\ No newline at end of file
+
+}
*/
package org.opendaylight.vpnservice.interfacemgr.servicebindings.flowbased.utilities;
-import com.google.common.base.Optional;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
-import org.opendaylight.vpnservice.mdsalutil.*;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.vpnservice.mdsalutil.MatchFieldType;
+import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
+import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil;
+import org.opendaylight.vpnservice.mdsalutil.NwConstants;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.ServiceBindings;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.StypeOpenflow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.ServicesInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.List;
+import com.google.common.base.Optional;
public class FlowBasedServicesUtils {
private static final Logger LOG = LoggerFactory.getLogger(FlowBasedServicesUtils.class);
matches.add(new MatchInfo(MatchFieldType.in_port, new BigInteger[] {dpId, BigInteger.valueOf(portNo)}));
int vlanId = 0;
IfL2vlan l2vlan = iface.getAugmentation(IfL2vlan.class);
- if(l2vlan != null && l2vlan.getVlanId() != null){
- vlanId = l2vlan.getVlanId().getValue();
+ if(l2vlan != null && l2vlan.getL2vlanMode() != IfL2vlan.L2vlanMode.Transparent){
+ vlanId = l2vlan.getVlanId() == null ? 0 : l2vlan.getVlanId().getValue();
}
if (vlanId > 0) {
matches.add(new MatchInfo(MatchFieldType.vlan_vid, new long[]{vlanId}));
}
String serviceRef = boundServiceNew.getServiceName();
- String flowRef = getFlowRef(dpId, iface.getName(), boundServiceNew);
+ String flowRef = getFlowRef(dpId, iface.getName(), boundServiceNew, boundServiceNew.getServicePriority());
StypeOpenflow stypeOpenflow = boundServiceNew.getAugmentation(StypeOpenflow.class);
Flow ingressFlow = MDSALUtil.buildFlowNew(tableId, flowRef,
stypeOpenflow.getFlowPriority(), serviceRef, 0, 0,
}
public static void installLPortDispatcherFlow(BigInteger dpId, BoundServices boundService, Interface iface,
- WriteTransaction t, int interfaceTag) {
+ WriteTransaction t, int interfaceTag, short currentServiceIndex, short nextServiceIndex) {
LOG.debug("Installing LPort Dispatcher Flows {}, {}", dpId, iface);
- short serviceIndex = boundService.getServicePriority();
String serviceRef = boundService.getServiceName();
List<MatchInfo> matches = FlowBasedServicesUtils.getMatchInfoForDispatcherTable(dpId, iface,
- interfaceTag, serviceIndex);
+ interfaceTag, currentServiceIndex);
// Get the metadata and mask from the service's write metadata instruction
StypeOpenflow stypeOpenFlow = boundService.getAugmentation(StypeOpenflow.class);
List<Instruction> serviceInstructions = stypeOpenFlow.getInstruction();
int instructionSize = serviceInstructions.size();
BigInteger[] metadataValues = IfmUtil.mergeOpenflowMetadataWriteInstructions(serviceInstructions);
- BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(interfaceTag, ++serviceIndex, metadataValues[0]);
+ BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(interfaceTag, nextServiceIndex, metadataValues[0]);
BigInteger metadataMask = MetaDataUtil.getMetaDataMaskForLPortDispatcher(MetaDataUtil.METADATA_MASK_SERVICE_INDEX,
MetaDataUtil.METADATA_MASK_LPORT_TAG, metadataValues[1]);
}
// build the flow and install it
- String flowRef = getFlowRef(dpId, iface.getName(), boundService);
- Flow ingressFlow = MDSALUtil.buildFlowNew(stypeOpenFlow.getDispatcherTableId(), flowRef,
+ String flowRef = getFlowRef(dpId, iface.getName(), boundService, currentServiceIndex);
+ Flow ingressFlow = MDSALUtil.buildFlowNew(NwConstants.LPORT_DISPATCHER_TABLE, flowRef,
boundService.getServicePriority(), serviceRef, 0, 0, stypeOpenFlow.getFlowCookie(), matches, instructions);
installFlow(dpId, ingressFlow, t);
}
public static void removeIngressFlow(Interface iface, BoundServices serviceOld, BigInteger dpId, WriteTransaction t) {
LOG.debug("Removing Ingress Flows");
- String flowKeyStr = getFlowRef(dpId, iface.getName(), serviceOld);
+ String flowKeyStr = getFlowRef(dpId, iface.getName(), serviceOld, serviceOld.getServicePriority());
FlowKey flowKey = new FlowKey(new FlowId(flowKeyStr));
Node nodeDpn = buildInventoryDpnNode(dpId);
InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
t.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
}
- public static void removeLPortDispatcherFlow(BigInteger dpId, Interface iface, BoundServices boundServicesOld, WriteTransaction t) {
+ public static void removeLPortDispatcherFlow(BigInteger dpId, Interface iface, BoundServices boundServicesOld, WriteTransaction t, short currentServiceIndex) {
LOG.debug("Removing LPort Dispatcher Flows {}, {}", dpId, iface);
StypeOpenflow stypeOpenFlow = boundServicesOld.getAugmentation(StypeOpenflow.class);
// build the flow and install it
- String flowRef = getFlowRef(dpId, iface.getName(), boundServicesOld);
+ String flowRef = getFlowRef(dpId, iface.getName(), boundServicesOld, currentServiceIndex);
FlowKey flowKey = new FlowKey(new FlowId(flowRef));
Node nodeDpn = buildInventoryDpnNode(dpId);
InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
t.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
}
- private static String getFlowRef(BigInteger dpnId, String iface, BoundServices service) {
- return new StringBuffer().append(dpnId).append( NwConstants.VLAN_INTERFACE_INGRESS_TABLE).append(NwConstants.FLOWID_SEPARATOR)
- .append(iface).append(NwConstants.FLOWID_SEPARATOR).append(service.getServiceName()).append(NwConstants.FLOWID_SEPARATOR)
- .append(service.getServicePriority()).toString();
+ private static String getFlowRef(BigInteger dpnId, String iface, BoundServices service, short currentServiceIndex) {
+ return new StringBuffer().append(dpnId).append(NwConstants.VLAN_INTERFACE_INGRESS_TABLE).append(NwConstants.FLOWID_SEPARATOR)
+ .append(iface).append(NwConstants.FLOWID_SEPARATOR).append(currentServiceIndex).toString();
+ }
+
+ /**
+ * This util method returns an array of ServiceInfo in which index 0 will
+ * have the immediate lower priority service and index 1 will have the
+ * immediate higher priority service among the list of existing serviceInfos
+ *
+ * @param serviceInfos
+ * @param currentServiceInfo
+ * @return
+ */
+ public static BoundServices[] getHighAndLowPriorityService(
+ List<BoundServices> serviceInfos, BoundServices currentServiceInfo) {
+ BoundServices higher = null; // this will be used to hold the immediate higher service priority with respect to the currentServiceInfo
+ BoundServices lower = null; // this will be used to hold the immediate lower service priority with respect to the currentServiceInfo
+ if (serviceInfos == null || serviceInfos.isEmpty()) {
+ return new BoundServices[]{lower, higher};
+ }
+ List <BoundServices> availableServiceInfos = new ArrayList<BoundServices>(serviceInfos);
+ Collections.sort(availableServiceInfos, new Comparator<BoundServices>() {
+ @Override
+ public int compare(BoundServices serviceInfo1, BoundServices serviceInfo2) {
+ return serviceInfo2.getServicePriority().compareTo(serviceInfo1.getServicePriority());
+ }
+ });
+ for (BoundServices availableServiceInfo: availableServiceInfos) {
+ if (currentServiceInfo.getServicePriority() > availableServiceInfo.getServicePriority()) {
+ lower = availableServiceInfo;
+ break;
+ } else {
+ higher = availableServiceInfo;
+ }
+ }
+ return new BoundServices[]{lower,higher};
+ }
+
+ public static BoundServices getHighestPriorityService(List<BoundServices> serviceInfos) {
+ List <BoundServices> availableServiceInfos = new ArrayList<BoundServices>(serviceInfos);
+ if (availableServiceInfos.isEmpty()) {
+ return null;
+ }
+ BoundServices highPriorityService = availableServiceInfos.get(0);
+ availableServiceInfos.remove(0);
+ for (BoundServices availableServiceInfo: availableServiceInfos) {
+ if (availableServiceInfo.getServicePriority() > highPriorityService.getServicePriority()) {
+ highPriorityService = availableServiceInfo;
+ }
+ }
+ return highPriorityService;
}
-}
\ No newline at end of file
+
+ public static void installVlanFlow(BigInteger dpId, long portNo, Interface iface,
+ WriteTransaction t, List<MatchInfo> matches, int lportTag) {
+ int vlanId = 0;
+ boolean isVlanTransparent = false;
+ IfL2vlan l2vlan = iface.getAugmentation(IfL2vlan.class);
+ if(l2vlan != null){
+ vlanId = l2vlan.getVlanId() == null ? 0 : l2vlan.getVlanId().getValue();
+ isVlanTransparent = l2vlan.getL2vlanMode() == IfL2vlan.L2vlanMode.Transparent;
+ }
+ int instructionKey = 0;
+ BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(lportTag, (short) 0);
+ BigInteger metadataMask = MetaDataUtil.getMetaDataMaskForLPortDispatcher();
+ List<Instruction> instructions = new ArrayList<Instruction>();
+ if (vlanId != 0 && !isVlanTransparent) {
+ instructions.add(MDSALUtil.buildAndGetPopVlanActionInstruction(lportTag, instructionKey++));
+ }
+ instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(metadata, metadataMask, instructionKey++));
+ instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.DHCP_TABLE, instructionKey++));
+ int priority = isVlanTransparent ? 1 : vlanId == 0 ? IfmConstants.FLOW_PRIORITY_FOR_UNTAGGED_VLAN : IfmConstants.FLOW_HIGH_PRIORITY;
+ String flowRef = getFlowRef(IfmConstants.VLAN_INTERFACE_INGRESS_TABLE, dpId, iface.getName());
+ Flow ingressFlow = MDSALUtil.buildFlowNew(IfmConstants.VLAN_INTERFACE_INGRESS_TABLE, flowRef, priority, flowRef, 0, 0,
+ IfmConstants.VLAN_TABLE_COOKIE, matches, instructions);
+ installFlow(dpId, ingressFlow, t);
+}
+
+ public static String getFlowRef(short tableId, BigInteger dpnId, String infName) {
+ return String.format("%d:%s:%s", tableId, dpnId, infName);
+ }
+
+ public static void removeIngressFlow(Interface iface, BigInteger dpId, WriteTransaction t) {
+ LOG.debug("Removing Ingress Flows");
+ String flowKeyStr = getFlowRef(IfmConstants.VLAN_INTERFACE_INGRESS_TABLE, dpId, iface.getName());
+ FlowKey flowKey = new FlowKey(new FlowId(flowKeyStr));
+ Node nodeDpn = buildInventoryDpnNode(dpId);
+ InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
+ .child(Table.class, new TableKey(NwConstants.VLAN_INTERFACE_INGRESS_TABLE)).child(Flow.class, flowKey).build();
+
+ t.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
+ }
+
+
+}
import com.google.common.base.Optional;
import com.google.common.util.concurrent.Futures;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
.setKey(IfmUtil.getStateInterfaceKeyFromName(InterfaceManagerTestUtil.interfaceName))
.setName(InterfaceManagerTestUtil.interfaceName);
- stypeOpenflow = InterfaceManagerTestUtil.buildStypeOpenflow(dpId, flowPriority,key,instructions);
+ stypeOpenflow = InterfaceManagerTestUtil.buildStypeOpenflow(dpId, flowPriority,NwConstants.LPORT_DISPATCHER_TABLE,instructions);
boundServiceNew = InterfaceManagerTestUtil.buildBoundServices(serviceName, key, new BoundServicesKey(key), stypeOpenflow);
instructionKey = new InstructionKey(instructionKeyval);
BigInteger[] metadataValues = IfmUtil.mergeOpenflowMetadataWriteInstructions(instructions);
List<Instruction> instructionList = boundServiceNew.getAugmentation(StypeOpenflow.class).getInstruction();
String serviceRef = boundServiceNew.getServiceName();
List<MatchInfo> matches = new ArrayList<>();
- matches.add(new MatchInfo(MatchFieldType.in_port, new BigInteger[] {dpId, BigInteger.valueOf(portNum)}));
- ingressFlow = MDSALUtil.buildFlowNew(stypeOpenflow.getDispatcherTableId(), flowRef, boundServiceNew.getServicePriority(), serviceRef, 0, 0,
+ matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+ MetaDataUtil.getMetaDataForLPortDispatcher(ifaceBuilder.getIfIndex(), boundServiceNew.getServicePriority()),
+ MetaDataUtil.getMetaDataMaskForLPortDispatcher() }));
+ ingressFlow = MDSALUtil.buildFlowNew(NwConstants.LPORT_DISPATCHER_TABLE, flowRef, boundServiceNew.getServicePriority(), serviceRef, 0, 0,
stypeOpenflow.getFlowCookie(), matches, instructionList);
FlowKey flowKey = new FlowKey(new FlowId(ingressFlow.getId()));
flowInstanceId = InterfaceManagerTestUtil.getFlowInstanceIdentifier(dpId,ingressFlow.getTableId(),flowKey);
import com.google.common.base.Optional;
import com.google.common.util.concurrent.Futures;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
Instruction instruction = null;
InstructionKey instructionKey = null;
List<Instruction>instructions = new ArrayList<>();
- short key =2;
+ short key =0;
int ifIndexval = 100;
int flowpriority = 2;
String serviceName = "VPN";
.setLowerLayerIf(lowerLayerIfList)
.setKey(IfmUtil.getStateInterfaceKeyFromName(InterfaceManagerTestUtil.interfaceName))
.setName(InterfaceManagerTestUtil.interfaceName);
- stypeOpenflow = InterfaceManagerTestUtil.buildStypeOpenflow(dpId,flowpriority, NwConstants.VLAN_INTERFACE_INGRESS_TABLE, instructions);
+ stypeOpenflow = InterfaceManagerTestUtil.buildStypeOpenflow(dpId,flowpriority, NwConstants.LPORT_DISPATCHER_TABLE, instructions);
instructionKey = new InstructionKey(instructionKeyval);
BigInteger[] metadataValues = IfmUtil.mergeOpenflowMetadataWriteInstructions(instructions);
boundService = InterfaceManagerTestUtil.buildBoundServices(serviceName,key,new BoundServicesKey(key),stypeOpenflow);
List<Instruction> instructionList = boundService.getAugmentation(StypeOpenflow.class).getInstruction();
String serviceRef = boundService.getServiceName();
List<MatchInfo> matches = new ArrayList<>();
- matches.add(new MatchInfo(MatchFieldType.in_port, new BigInteger[]{dpId, BigInteger.valueOf(portNum)}));
+ matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
+ MetaDataUtil.getMetaDataForLPortDispatcher(ifaceBuilder.getIfIndex(), boundService.getServicePriority()),
+ MetaDataUtil.getMetaDataMaskForLPortDispatcher() }));
ingressFlow = MDSALUtil.buildFlowNew(stypeOpenflow.getDispatcherTableId(), flowRef, boundService.getServicePriority(), serviceRef, 0, 0,
stypeOpenflow.getFlowCookie(), matches, instructionList);
FlowKey flowKey = new FlowKey(new FlowId(ingressFlow.getId()));
public static String buildflowRef(BigInteger dpId,String servicaName,String boundServicename, short servicePriority)
{
String flowRef = new StringBuffer().append(dpId).append(NwConstants.VLAN_INTERFACE_INGRESS_TABLE).append(NwConstants.FLOWID_SEPARATOR).
- append(servicaName).append(NwConstants.FLOWID_SEPARATOR).append(boundServicename).
- append(NwConstants.FLOWID_SEPARATOR).append(servicePriority).toString();
+ append(servicaName).append(NwConstants.FLOWID_SEPARATOR).append(servicePriority).toString();
return flowRef;
}
import com.google.common.base.Optional;
import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
import java.math.BigInteger;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.alivenessmonitor.rev150629.AlivenessMonitorService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutputBuilder;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
@RunWith(MockitoJUnitRunner.class)
public class VlanInterfaceConfigurationTest {
nodeConnectorInstanceIdentifier = InterfaceManagerTestUtil.getNcIdent("openflow:1", nodeConnectorId);
interfaceStateIdentifier = IfmUtil.buildStateInterfaceId(vlanInterfaceEnabled.getName());
stateInterface = InterfaceManagerTestUtil.buildStateInterface(InterfaceManagerTestUtil.interfaceName, nodeConnectorId);
+ AllocateIdOutput output = new AllocateIdOutputBuilder().setIdValue((long)1).build();
+ RpcResultBuilder<AllocateIdOutput> allocateIdRpcBuilder = RpcResultBuilder.success();
+ allocateIdRpcBuilder.withResult(output);
+ ListenableFuture<RpcResult<AllocateIdOutput>> future = Futures.immediateFuture(allocateIdRpcBuilder.build());
// Setup mocks
when(dataBroker.newReadOnlyTransaction()).thenReturn(mockReadTx);
when(dataBroker.newWriteOnlyTransaction()).thenReturn(mockWriteTx);
+
+ when(idManager.allocateId(any(AllocateIdInput.class))).thenReturn(future);
}
@Test
return null;
}
+ public static TransmitPacketInput getPacketOut(List<Action> actions, byte[] payload, BigInteger dpnId) {
+ NodeConnectorRef ncRef = getDefaultNodeConnRef(dpnId);
+ return new TransmitPacketInputBuilder()
+ .setAction(actions)
+ .setPayload(payload)
+ .setNode(
+ new NodeRef(InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class, new NodeKey(new NodeId("openflow:" + dpnId))).toInstance()))
+ .setIngress(ncRef).setEgress(ncRef).build();
+ }
+
}
public static final short L3_PROTOCOL_TABLE = 36;
public static final short L3_INTERFACE_TABLE = 80;
- public static final short LPORT_DISPATCHER_TABLE = 30;
+ public static final short LPORT_DISPATCHER_TABLE = 17;
public static final short VLAN_INTERFACE_INGRESS_TABLE = 0;
public static final short INTERNAL_TUNNEL_TABLE = 36;
public static final short EXTERNAL_TUNNEL_TABLE = 36;
+ public static final short DHCP_TABLE = 16;
- }
\ No newline at end of file
+ }
etherTypeClassMap.put(EtherTypes.LLDP.shortValue(), LLDP.class);
etherTypeClassMap.put(EtherTypes.IPv4.shortValue(), IPv4.class);
// TODO: Add support for more classes here
- // etherTypeClassMap.put(EtherTypes.VLANTAGGED.shortValue(), IEEE8021Q.class);
+ etherTypeClassMap.put(EtherTypes.VLANTAGGED.shortValue(), IEEE8021Q.class);
// etherTypeClassMap.put(EtherTypes.OLDQINQ.shortValue(), IEEE8021Q.class);
// etherTypeClassMap.put(EtherTypes.QINQ.shortValue(), IEEE8021Q.class);
// etherTypeClassMap.put(EtherTypes.CISCOQINQ.shortValue(), IEEE8021Q.class);
--- /dev/null
+/*
+ * 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.mdsalutil.packet;
+
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
+import org.opendaylight.controller.liblldp.BitBufferHelper;
+
+public class IEEE8021Q extends Ethernet {
+ private static final String PRIORITY = "Priority";
+ private static final String CFI = "CFI";
+ private static final String VLAN_ID = "VlanId";
+ private static final String ETHT = "EtherType";
+
+ private static Map<String, Pair<Integer, Integer>> fieldCoordinates = new LinkedHashMap<String, Pair<Integer, Integer>>() {
+ private static final long serialVersionUID = 1L;
+ {
+ put(PRIORITY, new ImmutablePair<Integer, Integer>(0, 3));
+ put(CFI, new ImmutablePair<Integer, Integer>(3, 1));
+ put(VLAN_ID, new ImmutablePair<Integer, Integer>(4, 12));
+ put(ETHT, new ImmutablePair<Integer, Integer>(16, 16));
+ }
+ };
+ private Map<String, byte[]> fieldValues;
+
+ /**
+ * Default constructor that creates and sets the HashMap
+ */
+ public IEEE8021Q() {
+ super();
+ fieldValues = new HashMap<String, byte[]>();
+ hdrFieldCoordMap = fieldCoordinates;
+ hdrFieldsMap = fieldValues;
+ }
+
+ public IEEE8021Q(boolean writeAccess) {
+ super(writeAccess);
+ fieldValues = new HashMap<String, byte[]>();
+ hdrFieldCoordMap = fieldCoordinates;
+ hdrFieldsMap = fieldValues;
+ }
+
+ public short getPriority() {
+ return (BitBufferHelper.getShort(fieldValues.get(PRIORITY)));
+ }
+
+ public short getCfi() {
+ return (BitBufferHelper.getShort(fieldValues.get(CFI)));
+ }
+
+ public short getVlanId() {
+ return (BitBufferHelper.getShort(fieldValues.get(VLAN_ID)));
+ }
+
+ @Override
+ public short getEtherType() {
+ return BitBufferHelper.getShort(fieldValues.get(ETHT));
+ }
+
+ public IEEE8021Q setPriority(short priority) {
+ byte[] priorityByte = BitBufferHelper.toByteArray(priority);
+ fieldValues.put(PRIORITY, priorityByte);
+ return this;
+ }
+
+ public IEEE8021Q setCFI(short cfi) {
+ byte[] cfiByte = BitBufferHelper
+ .toByteArray(cfi);
+ fieldValues.put(CFI, cfiByte);
+ return this;
+ }
+
+ public IEEE8021Q setVlanId(short vlanId) {
+ byte[] vlan = BitBufferHelper
+ .toByteArray(vlanId);
+ fieldValues.put(VLAN_ID, vlan);
+ return this;
+ }
+
+ @Override
+ public IEEE8021Q setEtherType(short etherType) {
+ byte[] ethType = BitBufferHelper.toByteArray(etherType);
+ fieldValues.put(ETHT, ethType);
+ return this;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result
+ + ((fieldValues == null) ? 0 : fieldValues.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ IEEE8021Q other = (IEEE8021Q) obj;
+ if (fieldValues == null) {
+ if (other.fieldValues != null) {
+ return false;
+ }
+ } else if (!fieldValues.equals(other.fieldValues)) {
+ return false;
+ }
+ return true;
+ }
+}