/*
- * Copyright (c) 2015, 2016 NEC Corporation. All rights reserved.
+ * Copyright (c) 2015, 2017 NEC Corporation. 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,
import org.opendaylight.vtn.manager.internal.TxQueue;
import org.opendaylight.vtn.manager.internal.VTNManagerProvider;
import org.opendaylight.vtn.manager.internal.util.IdentifiedData;
-import org.opendaylight.vtn.manager.internal.util.MiscUtils;
import org.opendaylight.vtn.manager.internal.util.flow.FlowCache;
import org.opendaylight.vtn.manager.internal.util.flow.FlowFinder;
import org.opendaylight.vtn.manager.internal.util.flow.FlowStatsUtils;
import org.opendaylight.vtn.manager.internal.util.flow.FlowUtils;
import org.opendaylight.vtn.manager.internal.util.flow.match.FlowMatchUtils;
+import org.opendaylight.vtn.manager.internal.util.inventory.NodeUtils;
import org.opendaylight.vtn.manager.internal.util.inventory.SalNode;
import org.opendaylight.vtn.manager.internal.util.log.VTNLogLevel;
import org.opendaylight.vtn.manager.internal.util.tx.AbstractTxTask;
vdf.getFlowId().getValue());
} else {
// Verify the ingress flow entry.
- flow = verifyIngressFlow(ctx, vdf, vfent, flow);
+ flow = verifyIngressFlow(ctx, ingressNode, vdf, vfent, flow);
}
}
* Verify the ingress flow entry of the VTN data flow.
*
* @param ctx MD-SAL datastore transaction context.
+ * @param snode A {@link SalNode} instance that specifies the ingress
+ * node.
* @param vdf The VTN data flow.
* @param vfent The ingress flow entry of the VTN data flow.
* @param flow The MD-SAL flow entry associated with the ingress flow
* entry.
* @return {@code flow} on success. {@code null} on failure.
*/
- private Flow verifyIngressFlow(TxContext ctx, VtnDataFlow vdf,
- VtnFlowEntry vfent, Flow flow) {
- // One VTN data flow should never installs more than one flow
- // entry into the same node.
+ private Flow verifyIngressFlow(TxContext ctx, SalNode snode,
+ VtnDataFlow vdf, VtnFlowEntry vfent,
+ Flow flow) {
+ // One VTN data flow should never install more than one flow entry
+ // into the same node.
NodeConnectorId vport =
FlowMatchUtils.getIngressPort(vfent.getMatch());
NodeConnectorId port = FlowMatchUtils.getIngressPort(flow.getMatch());
Flow result = null;
- if (MiscUtils.equalsUri(vport, port)) {
+ if (NodeUtils.equalsNodeConnectorId(snode, vport, port)) {
// Verify flow priority.
Integer vpri = vfent.getPriority();
Integer pri = flow.getPriority();
/*
- * Copyright (c) 2015, 2016 NEC Corporation. All rights reserved.
+ * Copyright (c) 2015, 2017 NEC Corporation. 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,
String tname, VtnDataFlow vdf) throws VTNException {
VtnDataFlowKey key = vdf.getKey();
BigInteger id = key.getFlowId().getValue();
- FlowId fid = FlowUtils.createMdFlowId(id);
+ FlowId fid = vdf.getSalFlowId();
+ if (fid == null) {
+ ctx.log(LOG, VTNLogLevel.TRACE,
+ "Use MD-SAL flow ID derived from VTN flow ID: {}", id);
+ fid = FlowUtils.createMdFlowId(id);
+ }
// Read flow statistics collected by the MD-SAL statistics manager.
FlowCache fc = new FlowCache(vdf);
/*
- * Copyright (c) 2014, 2016 NEC Corporation. All rights reserved.
+ * Copyright (c) 2014, 2017 NEC Corporation. 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,
package org.opendaylight.vtn.manager.internal.util.inventory;
+import org.opendaylight.vtn.manager.internal.util.MiscUtils;
import org.opendaylight.vtn.manager.internal.util.rpc.RpcException;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.impl.inventory.rev150209.vtn.node.info.VtnPort;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.types.rev150209.VtnPortDesc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+
/**
* {@code NodeUtils} class is a collection of utility class methods related to
* node-id and node-connector-id, aka switch and switch port identifier.
return new VtnPortDesc(builder.toString());
}
+ /**
+ * Determine whether the given two URIs are identical or not.
+ *
+ * @param snode A {@link SalNode} instance that specifies the node.
+ * This is used to parse node-connector-id that contains
+ * port number only.
+ * @param id1 The first node-connector-id to be compared.
+ * @param id2 The second node-connector-id to be compared.
+ * @return {@code true} only if {@code id1} and {@code id2} are identical.
+ */
+ public static boolean equalsNodeConnectorId(
+ SalNode snode, NodeConnectorId id1, NodeConnectorId id2) {
+ // At first try to compare as Uri string.
+ boolean ret = MiscUtils.equalsUri(id1, id2);
+ if (!ret) {
+ // Try to compare as SalPort.
+ SalPort sport1 = SalPort.create(snode, id1);
+ if (sport1 != null) {
+ ret = sport1.equals(SalPort.create(snode, id2));
+ }
+ }
+
+ return ret;
+ }
+
/**
* Check whether the given parameters specifies a valid switch port or not.
*
/*
- * Copyright (c) 2015 NEC Corporation. All rights reserved.
+ * Copyright (c) 2015, 2017 NEC Corporation. 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,
return create(id.getValue());
}
+ /**
+ * Convert a MD-SAL node connector ID into a {@code SalPort} instance.
+ *
+ * @param snode A {@link SalNode} instance that specifies the node.
+ * This parameter is used only if {@code id} does not contain
+ * node ID.
+ * @param id A {@link NodeConnectorId} instance.
+ * @return A {@code SalPort} instance on success.
+ * {@code null} on failure.
+ */
+ public static SalPort create(SalNode snode, NodeConnectorId id) {
+ SalPort sport = create(id);
+ if (sport == null && snode != null && id != null) {
+ // node-connector-id may contain only a port ID.
+ sport = create(snode.getNodeNumber(), id.getValue());
+ }
+
+ return sport;
+ }
+
/**
* Convert a MD-SAL node connector reference into a {@code SalPort}
* instance.
--- /dev/null
+/*
+ * Copyright (c) 2017 NEC Corporation. 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.vtn.manager.internal;
+
+import java.util.Objects;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+
+/**
+ * An implementation of {@link NodeConnectorId} that bypasses value check.
+ */
+public final class TestNodeConnectorId extends NodeConnectorId {
+ /**
+ * A value of node-connector-id.
+ */
+ private final String value;
+
+ /**
+ * Construct an empty instance.
+ */
+ public TestNodeConnectorId() {
+ this(null);
+ }
+
+ /**
+ * Construct a new instance.
+ *
+ * @param v A value of node-connector-id.
+ */
+ public TestNodeConnectorId(String v) {
+ super("openflow:1:2");
+ value = v;
+ }
+
+ // Uri
+
+ /**
+ * Return the value of this node-connector-id.
+ *
+ * @return The value of this node-connector-id.
+ */
+ @Override
+ public String getValue() {
+ return value;
+ }
+
+ // Object
+
+ /**
+ * Determine whether the given object is identical to this object.
+ *
+ * @param o An object to be compared.
+ * @return {@code true} if identical. Otherwise {@code false}.
+ */
+ @Override
+ public boolean equals(Object o) {
+ boolean ret = (o == this);
+ if (!ret && o != null && getClass().equals(o.getClass())) {
+ TestNodeConnectorId ncId = (TestNodeConnectorId)o;
+ ret = Objects.equals(value, ncId.value);
+ }
+
+ return ret;
+ }
+
+ /**
+ * Return the hash code of this object.
+ *
+ * @return The hash code.
+ */
+ @Override
+ public int hashCode() {
+ return Objects.hash(getClass(), value);
+ }
+}
/*
- * Copyright (c) 2014, 2015 NEC Corporation. All rights reserved.
+ * Copyright (c) 2014, 2017 NEC Corporation. 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,
package org.opendaylight.vtn.manager.internal.util.inventory;
+import static org.opendaylight.vtn.manager.internal.util.inventory.NodeUtils.equalsNodeConnectorId;
+
+import java.math.BigInteger;
+
import org.junit.Test;
import org.opendaylight.vtn.manager.internal.util.rpc.RpcErrorTag;
import org.opendaylight.vtn.manager.internal.util.rpc.RpcException;
import org.opendaylight.vtn.manager.internal.TestBase;
+import org.opendaylight.vtn.manager.internal.TestNodeConnectorId;
import org.opendaylight.vtn.manager.internal.TestVtnPortDesc;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.impl.inventory.rev150209.vtn.node.info.VtnPort;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.types.rev150209.VtnErrorTag;
import org.opendaylight.yang.gen.v1.urn.opendaylight.vtn.types.rev150209.VtnPortDesc;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+
/**
* JUnit test for {@link NodeUtils}.
*/
}
}
}
+
+ /**
+ * Test case for
+ * {@link NodeUtils#equalsNodeConnectorId(SalNode, NodeConnectorId, NodeConnectorId)}.
+ */
+ @Test
+ public void testEqualsNodeConnectorId() {
+ BigInteger[] nodeIds = {
+ BigInteger.ONE,
+ BigInteger.valueOf(2L),
+ BigInteger.valueOf(7777777L),
+ BigInteger.valueOf(0x123456789L),
+ new BigInteger("18446744073709551615"),
+ };
+ SalNode anotherNode = new SalNode(999L);
+
+ long[] portIds = {
+ 1L, 2L, 345L, 6789L, 0xabcdefL, 0xffffff00L,
+ };
+
+ SalNode nullNode = null;
+ NodeConnectorId nullNcId = null;
+ NodeConnectorId empty1 = new TestNodeConnectorId();
+ NodeConnectorId empty2 = new TestNodeConnectorId();
+
+ NodeConnectorId[] badIds = {
+ null, empty1,
+
+ // Invalid node type.
+ new NodeConnectorId(""),
+ new NodeConnectorId("proto1:1:3"),
+ new NodeConnectorId("of:2:1"),
+ new NodeConnectorId("openflow1:1:4"),
+
+ // Too large DPID.
+ new NodeConnectorId("openflow:18446744073709551616:3"),
+ new NodeConnectorId("openflow:18446744073709551617:2"),
+ new NodeConnectorId("openflow:99999999999999999999999:2"),
+ new NodeConnectorId("openflow:999999999999999999999999:LOCAL"),
+
+ // Negative DPID.
+ new NodeConnectorId("openflow:-1:1"),
+ new NodeConnectorId("openflow:-12345678:2"),
+ new NodeConnectorId("openflow:-3333333333333333333333333:2"),
+
+ // Invalid DPID.
+ new NodeConnectorId("openflow:0x12345678:1"),
+ new NodeConnectorId("openflow:1234abcd:1"),
+ new NodeConnectorId("openflow:Bad DPID:1"),
+
+ // Invalid port number.
+ new NodeConnectorId("4294967041"),
+ new NodeConnectorId("4294967042"),
+ new NodeConnectorId("4294967295"),
+ new NodeConnectorId("9999999999999999999999999999"),
+ new NodeConnectorId("-1"),
+ new NodeConnectorId("-2"),
+ new NodeConnectorId("-1000000"),
+ new NodeConnectorId("abcde"),
+ new NodeConnectorId("bad port ID"),
+ };
+
+ for (BigInteger nodeId: nodeIds) {
+ SalNode snode = new SalNode(nodeId.longValue());
+ SalNode[] snodes = {nullNode, snode, anotherNode};
+ for (long portId1: portIds) {
+ for (long portId2: portIds) {
+ // In case where both node-connector-ids are
+ // fully-qualified.
+ String str1 = String.format("openflow:%s:%d",
+ nodeId, portId1);
+ String str2 = String.format("openflow:%s:%d",
+ nodeId, portId2);
+ NodeConnectorId id1 = new NodeConnectorId(str1);
+ NodeConnectorId id2 = new NodeConnectorId(str2);
+ boolean match = (portId1 == portId2);
+ for (SalNode sn: snodes) {
+ assertEquals(match,
+ equalsNodeConnectorId(sn, id1, id2));
+ }
+
+ // In case where only one node-connector-id is
+ // fully-qualified.
+ str2 = Long.toString(portId2);
+ id2 = new NodeConnectorId(str2);
+ for (SalNode sn: snodes) {
+ boolean expected = (match && snode.equals(sn));
+ assertEquals(expected,
+ equalsNodeConnectorId(sn, id1, id2));
+ assertEquals(expected,
+ equalsNodeConnectorId(sn, id2, id1));
+ }
+
+ // Should return if one node-connector-id is invalid.
+ NodeConnectorId[] ids = {id1, id2};
+ for (SalNode sn: snodes) {
+ for (NodeConnectorId id: ids) {
+ for (NodeConnectorId bad: badIds) {
+ assertFalse(equalsNodeConnectorId(sn, id, bad));
+ assertFalse(equalsNodeConnectorId(sn, bad, id));
+ }
+ }
+ }
+
+ // In case where both node-connector-ids are specified by
+ // port number.
+ str1 = Long.toString(portId1);
+ id1 = new NodeConnectorId(str1);
+ if (match) {
+ assertEquals(id2, id1);
+ } else {
+ assertNotEquals(id2, id1);
+ }
+ for (SalNode sn: snodes) {
+ assertEquals(match,
+ equalsNodeConnectorId(sn, id1, id2));
+ }
+ }
+ }
+
+ for (SalNode sn: snodes) {
+ // Should return true if both node-connector-ids are null.
+ assertTrue(equalsNodeConnectorId(sn, nullNcId, nullNcId));
+ assertFalse(equalsNodeConnectorId(sn, empty1, nullNcId));
+ assertFalse(equalsNodeConnectorId(sn, nullNcId, empty1));
+
+ // Should return true if both node-connector-ids are empty.
+ assertTrue(equalsNodeConnectorId(sn, empty1, empty2));
+ }
+ }
+ }
}
/*
- * Copyright (c) 2015, 2016 NEC Corporation. All rights reserved.
+ * Copyright (c) 2015, 2017 NEC Corporation. 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,
import org.opendaylight.vtn.manager.internal.util.pathpolicy.PathPolicyUtils;
import org.opendaylight.vtn.manager.internal.TestBase;
+import org.opendaylight.vtn.manager.internal.TestNodeConnectorId;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
}
}
+ /**
+ * Test case for {@link SalPort#create(SalNode, NodeConnectorId)}.
+ */
+ @Test
+ public void testCreateNodeConnectorId() {
+ BigInteger[] nodeIds = {
+ BigInteger.ONE,
+ BigInteger.valueOf(2L),
+ BigInteger.valueOf(345678L),
+ BigInteger.valueOf(0x12345678L),
+ new BigInteger("18446744073709551615"),
+ };
+ long[] portIds = {
+ 1L, 2L, 3456789L, 0xabcdefL, 0xffffff00L,
+ };
+
+ String[] bad = {
+ // Invalid node type.
+ "",
+ "proto1:1:3",
+ "of:2:1",
+ "openflow1:1:4",
+
+ // Too large DPID.
+ "openflow:18446744073709551616:3",
+ "openflow:18446744073709551617:2",
+ "openflow:99999999999999999999999:2",
+ "openflow:999999999999999999999999:LOCAL",
+
+ // Negative DPID.
+ "openflow:-1:1",
+ "openflow:-12345678:2",
+ "openflow:-3333333333333333333333333:2",
+
+ // Invalid DPID.
+ "openflow:0x12345678:1",
+ "openflow:1234abcd:1",
+ "openflow:Bad DPID:1",
+
+ // Invalid port number.
+ "4294967041",
+ "4294967042",
+ "4294967295",
+ "9999999999999999999999999999",
+ "-1",
+ "-2",
+ "-1000000",
+ "abcde",
+ "bad port ID",
+ };
+
+ SalNode nullNode = null;
+ NodeConnectorId nullNcId = null;
+ NodeConnectorId emptyNcId = new TestNodeConnectorId();
+
+ // Should return false if both SalNode and node-connector-id are null.
+ assertNull(SalPort.create(nullNode, nullNcId));
+
+ for (BigInteger nodeId: nodeIds) {
+ SalNode snode = new SalNode(nodeId.longValue());
+
+ // Should return false if node-connector-id is null.
+ assertNull(SalPort.create(snode, nullNcId));
+
+ // Should return false if node-connector-id is empty.
+ assertNull(SalPort.create(snode, emptyNcId));
+
+ for (long portId: portIds) {
+ // SalNode should be ignored if node-connector-id is
+ // fully-qualified.
+ NodeConnectorId ncId = new NodeConnectorId(
+ String.format("openflow:%s:%d", nodeId, portId));
+ SalNode[] snodes = {nullNode, snode};
+ for (SalNode sn: snodes) {
+ SalPort sport = SalPort.create(sn, ncId);
+ assertNotNull(sport);
+ assertEquals(nodeId.longValue(), sport.getNodeNumber());
+ assertEquals(portId, sport.getPortNumber());
+ }
+
+ // In case where node-connector-id contains port number only.
+ ncId = new NodeConnectorId(Long.toString(portId));
+ SalPort sport = SalPort.create(snode, ncId);
+ assertNotNull(sport);
+ assertEquals(nodeId.longValue(), sport.getNodeNumber());
+ assertEquals(portId, sport.getPortNumber());
+
+ // Should return false if SalNode is null.
+ assertNull(SalPort.create(nullNode, ncId));
+ }
+
+ // Should return false if node-connector-id is invalid.
+ for (String id: bad) {
+ NodeConnectorId ncId = new NodeConnectorId(id);
+ assertNull(SalPort.create(snode, ncId));
+ }
+ }
+ }
+
/**
* Test case for {@link SalPort#create(VtnPortLocation)}.
*/