From: Devin Avery Date: Fri, 27 Jun 2014 15:52:38 +0000 (+0000) Subject: Merge "Bug 1227: Removed #close() from Write Transactions." X-Git-Tag: release/helium~594 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=3ce420ccd45e7530c2c2158bd57462fd5859a879;hp=d7d5c4d3e7eaed528961081718c47a0960517ace Merge "Bug 1227: Removed #close() from Write Transactions." --- diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.java index 90134e6278..fa25122bba 100644 --- a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.java +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.java @@ -7,11 +7,8 @@ */ package org.opendaylight.controller.sal.compatibility; -import java.math.BigInteger; -import java.util.Date; -import java.util.HashSet; -import java.util.List; - +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; import org.opendaylight.controller.sal.common.util.Arguments; import org.opendaylight.controller.sal.core.AdvertisedBandwidth; import org.opendaylight.controller.sal.core.Bandwidth; @@ -45,6 +42,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.fl import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortConfig; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortFeatures; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.flow.capable.port.State; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.OutputPortValues; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdated; @@ -58,8 +56,10 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.N import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import com.google.common.base.Objects; -import com.google.common.base.Preconditions; +import java.math.BigInteger; +import java.util.Date; +import java.util.HashSet; +import java.util.List; public final class NodeMapping { @@ -153,15 +153,15 @@ public final class NodeMapping { } public static NodeConnectorId toControllerNodeConnectorId(final NodeId node) { - return new NodeConnectorId(node.getValue() + ":" + 4294967293L); + return new NodeConnectorId(node.getValue() + ":" + OutputPortValues.CONTROLLER.toString()); } public static NodeConnectorId toLocalNodeConnectorId(final NodeId node) { - return new NodeConnectorId(node.getValue() + ":" + 4294967294L); + return new NodeConnectorId(node.getValue() + ":" + OutputPortValues.LOCAL.toString()); } public static NodeConnectorId toNormalNodeConnectorId(final NodeId node) { - return new NodeConnectorId(node.getValue() + ":" + 4294967290L); + return new NodeConnectorId(node.getValue() + ":" + OutputPortValues.NORMAL.toString()); } public static NodeRef toNodeRef(final org.opendaylight.controller.sal.core.Node node) { diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/NodeMappingTest.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/NodeMappingTest.java index f986310644..8a23ebc933 100644 --- a/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/NodeMappingTest.java +++ b/opendaylight/md-sal/compatibility/sal-compatibility/src/test/java/org/opendaylight/controller/sal/compatibility/test/NodeMappingTest.java @@ -14,6 +14,7 @@ import org.opendaylight.controller.sal.core.ConstructionException; import org.opendaylight.controller.sal.core.MacAddress; import org.opendaylight.controller.sal.core.Node.NodeIDType; import org.opendaylight.controller.sal.core.NodeConnector.NodeConnectorIDType; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.OutputPortValues; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector; @@ -115,13 +116,13 @@ public class NodeMappingTest { ncId = buildNodeConnectorId("1", "42"); Assert.assertEquals(NodeConnectorIDType.OPENFLOW, NodeMapping.toNodeConnectorType(ncId, nodeId )); - ncId = buildNodeConnectorId("1", "4294967293"); + ncId = buildNodeConnectorId("1", OutputPortValues.CONTROLLER.toString()); Assert.assertEquals(NodeConnectorIDType.CONTROLLER, NodeMapping.toNodeConnectorType(ncId, nodeId )); - ncId = buildNodeConnectorId("1", "4294967290"); + ncId = buildNodeConnectorId("1", OutputPortValues.NORMAL.toString()); Assert.assertEquals(NodeConnectorIDType.HWPATH, NodeMapping.toNodeConnectorType(ncId, nodeId )); - ncId = buildNodeConnectorId("1", "4294967294"); + ncId = buildNodeConnectorId("1", OutputPortValues.LOCAL.toString()); Assert.assertEquals(NodeConnectorIDType.SWSTACK, NodeMapping.toNodeConnectorType(ncId, nodeId )); } diff --git a/opendaylight/md-sal/model/model-flow-base/src/main/yang/opendaylight-match-types.yang b/opendaylight/md-sal/model/model-flow-base/src/main/yang/opendaylight-match-types.yang index efe1ce3e3a..deff6f1798 100644 --- a/opendaylight/md-sal/model/model-flow-base/src/main/yang/opendaylight-match-types.yang +++ b/opendaylight/md-sal/model/model-flow-base/src/main/yang/opendaylight-match-types.yang @@ -275,6 +275,17 @@ module opendaylight-match-types { } } + grouping "tunnel-ipv4-match-fields" { + leaf tunnel-ipv4-source { + description "IPv4 source tunnel endpoint address."; + type inet:ipv4-prefix; + } + leaf tunnel-ipv4-destination { + description "IPv4 destination tunnel endpoint address."; + type inet:ipv4-prefix; + } + } + grouping match { leaf in-port { type inv:node-connector-id; @@ -321,6 +332,9 @@ module opendaylight-match-types { case "arp-match" { uses "arp-match-fields"; } + case "tunnel-ipv4-match" { + uses "tunnel-ipv4-match-fields"; + } } choice layer-4-match { diff --git a/opendaylight/md-sal/model/model-flow-base/src/main/yang/opendaylight-port-types.yang b/opendaylight/md-sal/model/model-flow-base/src/main/yang/opendaylight-port-types.yang index f1cbd8dc29..9e88098752 100644 --- a/opendaylight/md-sal/model/model-flow-base/src/main/yang/opendaylight-port-types.yang +++ b/opendaylight/md-sal/model/model-flow-base/src/main/yang/opendaylight-port-types.yang @@ -62,7 +62,10 @@ module opendaylight-port-types { grouping common-port { leaf port-number { - type uint32; + type union { + type uint32; + type string; + } } leaf hardware-address { diff --git a/opendaylight/md-sal/model/model-flow-base/src/main/yang/opendaylight-table-types.yang b/opendaylight/md-sal/model/model-flow-base/src/main/yang/opendaylight-table-types.yang index c271f8f4d0..393f6db9fe 100644 --- a/opendaylight/md-sal/model/model-flow-base/src/main/yang/opendaylight-table-types.yang +++ b/opendaylight/md-sal/model/model-flow-base/src/main/yang/opendaylight-table-types.yang @@ -192,6 +192,14 @@ module opendaylight-table-types { base match-field; description "TCP Flag Match"; } + identity tunnel_ipv4_dst { + base match-field; + description "IPv4 destination tunnel endpoint address."; + } + identity tunnel_ipv4_src { + base match-field; + description "IPv4 source tunnel endpoint address."; + } grouping set-field-match { list set-field-match { diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonMapper.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonMapper.java index 1e5bfbd6b9..696bf71535 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonMapper.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/impl/JsonMapper.java @@ -9,15 +9,15 @@ package org.opendaylight.controller.sal.rest.impl; import static com.google.common.base.Preconditions.checkNotNull; +import com.google.common.base.Preconditions; +import com.google.gson.stream.JsonWriter; import java.io.IOException; import java.net.URI; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; - import javax.activation.UnsupportedDataTypeException; - import org.opendaylight.controller.sal.core.api.mount.MountInstance; import org.opendaylight.controller.sal.restconf.impl.ControllerContext; import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO; @@ -29,6 +29,7 @@ import org.opendaylight.yangtools.yang.data.api.CompositeNode; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.Node; import org.opendaylight.yangtools.yang.data.api.SimpleNode; +import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode; import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode; import org.opendaylight.yangtools.yang.model.api.ChoiceNode; import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; @@ -48,13 +49,8 @@ import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinit import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.base.Preconditions; -import com.google.gson.stream.JsonWriter; - class JsonMapper { - private final Set foundLeafLists = new HashSet<>(); - private final Set foundLists = new HashSet<>(); private MountInstance mountPoint; private final Logger logger = LoggerFactory.getLogger(JsonMapper.class); @@ -77,15 +73,14 @@ class JsonMapper { } writer.endObject(); - - foundLeafLists.clear(); - foundLists.clear(); } private void writeChildrenOfParent(final JsonWriter writer, final CompositeNode parent, final DataNodeContainer parentSchema) throws IOException { checkNotNull(parent); + final Set foundLists = new HashSet<>(); + Set parentSchemaChildNodes = parentSchema == null ? Collections.emptySet() : parentSchema.getChildNodes(); @@ -98,59 +93,88 @@ class JsonMapper { logger.debug( "No schema found for data node \"" + child.getNodeType() ); - handleNoSchemaFound( writer, child, parent ); + if( !foundLists.contains( child.getNodeType() ) ) { + handleNoSchemaFound( writer, child, parent ); + + // Since we don't have a schema, we don't know which nodes are supposed to be + // lists so treat every one as a potential list to avoid outputting duplicates. + + foundLists.add( child.getNodeType() ); + } } else if (childSchema instanceof ContainerSchemaNode) { Preconditions.checkState(child instanceof CompositeNode, "Data representation of Container should be CompositeNode - " + child.getNodeType()); writeContainer(writer, (CompositeNode) child, (ContainerSchemaNode) childSchema); } else if (childSchema instanceof ListSchemaNode) { - if (!foundLists.contains(childSchema)) { + if (!foundLists.contains( child.getNodeType() ) ) { Preconditions.checkState(child instanceof CompositeNode, "Data representation of List should be CompositeNode - " + child.getNodeType()); - foundLists.add((ListSchemaNode) childSchema); + foundLists.add( child.getNodeType() ); writeList(writer, parent, (CompositeNode) child, (ListSchemaNode) childSchema); } } else if (childSchema instanceof LeafListSchemaNode) { - if (!foundLeafLists.contains(childSchema)) { + if (!foundLists.contains( child.getNodeType() ) ) { Preconditions.checkState(child instanceof SimpleNode, "Data representation of LeafList should be SimpleNode - " + child.getNodeType()); - foundLeafLists.add((LeafListSchemaNode) childSchema); + foundLists.add( child.getNodeType() ); writeLeafList(writer, parent, (SimpleNode) child, (LeafListSchemaNode) childSchema); } } else if (childSchema instanceof LeafSchemaNode) { Preconditions.checkState(child instanceof SimpleNode, "Data representation of LeafList should be SimpleNode - " + child.getNodeType()); writeLeaf(writer, (SimpleNode) child, (LeafSchemaNode) childSchema); + } else if (childSchema instanceof AnyXmlSchemaNode) { + if( child instanceof CompositeNode ) { + writeContainer(writer, (CompositeNode) child, null); + } + else { + handleNoSchemaFound( writer, child, parent ); + } } else { throw new UnsupportedDataTypeException("Schema can be ContainerSchemaNode, ListSchemaNode, " + "LeafListSchemaNode, or LeafSchemaNode. Other types are not supported yet."); } } + } - for (Node child : parent.getValue()) { - DataSchemaNode childSchema = findFirstSchemaForNode(child, parentSchemaChildNodes); - if (childSchema instanceof LeafListSchemaNode) { - foundLeafLists.remove(childSchema); - } else if (childSchema instanceof ListSchemaNode) { - foundLists.remove(childSchema); - } + private void writeValue( final JsonWriter writer, Object value ) throws IOException { + if( value != null ) { + writer.value( String.valueOf( value ) ); + } + else { + writer.value( "" ); } } private void handleNoSchemaFound( final JsonWriter writer, final Node node, final CompositeNode parent ) throws IOException { if( node instanceof SimpleNode ) { - writeName( node, null, writer ); - Object value = node.getValue(); - if( value != null ) { - writer.value( String.valueOf( value ) ); + List> nodeLeafList = parent.getSimpleNodesByName( node.getNodeType() ); + if( nodeLeafList.size() == 1 ) { + writeName( node, null, writer ); + writeValue( writer, node.getValue() ); + } + else { // more than 1, write as a json array + writeName( node, null, writer ); + writer.beginArray(); + for( SimpleNode leafNode: nodeLeafList ) { + writeValue( writer, leafNode.getValue() ); + } + + writer.endArray(); } } else { // CompositeNode Preconditions.checkState( node instanceof CompositeNode, "Data representation of Container should be CompositeNode - " + node.getNodeType() ); - writeContainer( writer, (CompositeNode) node, null ); + List nodeList = parent.getCompositesByName( node.getNodeType() ); + if( nodeList.size() == 1 ) { + writeContainer( writer, (CompositeNode) node, null ); + } + else { // more than 1, write as a json array + writeList( writer, parent, (CompositeNode) node, null ); + } } } diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.java index b0916f4500..6330c0a479 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.java @@ -36,6 +36,7 @@ import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.InstanceIdent import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; +import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode; import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode; import org.opendaylight.yangtools.yang.model.api.ChoiceNode; import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; @@ -804,7 +805,8 @@ public class ControllerContext implements SchemaContextListener { public boolean isInstantiatedDataSchema( final DataSchemaNode node ) { return node instanceof LeafSchemaNode || node instanceof LeafListSchemaNode || - node instanceof ContainerSchemaNode || node instanceof ListSchemaNode; + node instanceof ContainerSchemaNode || node instanceof ListSchemaNode || + node instanceof AnyXmlSchemaNode; } private void addKeyValue( final HashMap map, final DataSchemaNode node, diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java index 9700d48bc2..4716a02be2 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestconfImpl.java @@ -56,6 +56,7 @@ import org.opendaylight.yangtools.yang.data.api.Node; import org.opendaylight.yangtools.yang.data.api.SimpleNode; import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode; import org.opendaylight.yangtools.yang.data.impl.NodeFactory; +import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode; import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; @@ -1044,97 +1045,127 @@ public class RestconfImpl implements RestconfService { } } - if ((nodeBuilder instanceof CompositeNodeWrapper)) { - final List> children = ((CompositeNodeWrapper) nodeBuilder).getValues(); - for (final NodeWrapper child : children) { - final List potentialSchemaNodes = - this.controllerContext.findInstanceDataChildrenByName( - ((DataNodeContainer) schema), child.getLocalName()); + if ( nodeBuilder instanceof CompositeNodeWrapper ) { + if( schema instanceof DataNodeContainer ) { + normalizeCompositeNode( (CompositeNodeWrapper)nodeBuilder, (DataNodeContainer)schema, + mountPoint, currentAugment ); + } + else if( schema instanceof AnyXmlSchemaNode ) { + normalizeAnyXmlNode( (CompositeNodeWrapper)nodeBuilder, (AnyXmlSchemaNode)schema ); + } + } + else if ( nodeBuilder instanceof SimpleNodeWrapper ) { + normalizeSimpleNode( (SimpleNodeWrapper) nodeBuilder, schema, mountPoint ); + } + else if ((nodeBuilder instanceof EmptyNodeWrapper)) { + normalizeEmptyNode( (EmptyNodeWrapper) nodeBuilder, schema ); + } + } - if (potentialSchemaNodes.size() > 1 && child.getNamespace() == null) { - StringBuilder builder = new StringBuilder(); - for (final DataSchemaNode potentialSchemaNode : potentialSchemaNodes) { - builder.append(" ").append(potentialSchemaNode.getQName().getNamespace().toString()) - .append("\n"); - } + private void normalizeAnyXmlNode( CompositeNodeWrapper compositeNode, AnyXmlSchemaNode schema ) { + List> children = compositeNode.getValues(); + for( NodeWrapper child : children ) { + child.setNamespace( schema.getQName().getNamespace() ); + if( child instanceof CompositeNodeWrapper ) { + normalizeAnyXmlNode( (CompositeNodeWrapper)child, schema ); + } + } + } - throw new RestconfDocumentedException( - "Node \"" + child.getLocalName() + - "\" is added as augment from more than one module. " + - "Therefore node must have namespace (XML format) or module name (JSON format)." + - "\nThe node is added as augment from modules with namespaces:\n" + builder, - ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE ); - } + private void normalizeEmptyNode( EmptyNodeWrapper emptyNodeBuilder, DataSchemaNode schema ) { + if ((schema instanceof LeafSchemaNode)) { + emptyNodeBuilder.setComposite(false); + } + else { + if ((schema instanceof ContainerSchemaNode)) { + // FIXME: Add presence check + emptyNodeBuilder.setComposite(true); + } + } + } + + private void normalizeSimpleNode( SimpleNodeWrapper simpleNode, DataSchemaNode schema, + MountInstance mountPoint ) { + final Object value = simpleNode.getValue(); + Object inputValue = value; + TypeDefinition typeDefinition = this.typeDefinition(schema); + if ((typeDefinition instanceof IdentityrefTypeDefinition)) { + if ((value instanceof String)) { + inputValue = new IdentityValuesDTO( simpleNode.getNamespace().toString(), + (String) value, null, (String) value ); + } // else value is already instance of IdentityValuesDTO + } + + Object outputValue = inputValue; + + if( typeDefinition != null ) { + Codec codec = RestCodec.from(typeDefinition, mountPoint); + outputValue = codec == null ? null : codec.deserialize(inputValue); + } + + simpleNode.setValue(outputValue); + } - boolean rightNodeSchemaFound = false; + private void normalizeCompositeNode( CompositeNodeWrapper compositeNodeBuilder, + DataNodeContainer schema, MountInstance mountPoint, + QName currentAugment ) { + final List> children = compositeNodeBuilder.getValues(); + for (final NodeWrapper child : children) { + final List potentialSchemaNodes = + this.controllerContext.findInstanceDataChildrenByName( + schema, child.getLocalName()); + + if (potentialSchemaNodes.size() > 1 && child.getNamespace() == null) { + StringBuilder builder = new StringBuilder(); for (final DataSchemaNode potentialSchemaNode : potentialSchemaNodes) { - if (!rightNodeSchemaFound) { - final QName potentialCurrentAugment = - this.normalizeNodeName(child, potentialSchemaNode, currentAugment, mountPoint); - if (child.getQname() != null ) { - this.normalizeNode(child, potentialSchemaNode, potentialCurrentAugment, mountPoint); - rightNodeSchemaFound = true; - } - } + builder.append(" ").append(potentialSchemaNode.getQName().getNamespace().toString()) + .append("\n"); } - if (!rightNodeSchemaFound) { - throw new RestconfDocumentedException( - "Schema node \"" + child.getLocalName() + "\" was not found in module.", - ErrorType.APPLICATION, ErrorTag.UNKNOWN_ELEMENT ); - } + throw new RestconfDocumentedException( + "Node \"" + child.getLocalName() + + "\" is added as augment from more than one module. " + + "Therefore node must have namespace (XML format) or module name (JSON format)." + + "\nThe node is added as augment from modules with namespaces:\n" + builder, + ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE ); } - if ((schema instanceof ListSchemaNode)) { - final List listKeys = ((ListSchemaNode) schema).getKeyDefinition(); - for (final QName listKey : listKeys) { - boolean foundKey = false; - for (final NodeWrapper child : children) { - if (Objects.equal(child.unwrap().getNodeType().getLocalName(), listKey.getLocalName())) { - foundKey = true; - } - } - - if (!foundKey) { - throw new RestconfDocumentedException( - "Missing key in URI \"" + listKey.getLocalName() + - "\" of list \"" + schema.getQName().getLocalName() + "\"", - ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE ); + boolean rightNodeSchemaFound = false; + for (final DataSchemaNode potentialSchemaNode : potentialSchemaNodes) { + if (!rightNodeSchemaFound) { + final QName potentialCurrentAugment = + this.normalizeNodeName(child, potentialSchemaNode, currentAugment, mountPoint); + if (child.getQname() != null ) { + this.normalizeNode(child, potentialSchemaNode, potentialCurrentAugment, mountPoint); + rightNodeSchemaFound = true; } } } - } - else { - if ((nodeBuilder instanceof SimpleNodeWrapper)) { - final SimpleNodeWrapper simpleNode = ((SimpleNodeWrapper) nodeBuilder); - final Object value = simpleNode.getValue(); - Object inputValue = value; - TypeDefinition typeDefinition = this.typeDefinition(schema); - if ((typeDefinition instanceof IdentityrefTypeDefinition)) { - if ((value instanceof String)) { - inputValue = new IdentityValuesDTO( nodeBuilder.getNamespace().toString(), - (String) value, null, (String) value ); - } // else value is already instance of IdentityValuesDTO - } - Codec codec = RestCodec.from(typeDefinition, mountPoint); - Object outputValue = codec == null ? null : codec.deserialize(inputValue); - - simpleNode.setValue(outputValue); + if (!rightNodeSchemaFound) { + throw new RestconfDocumentedException( + "Schema node \"" + child.getLocalName() + "\" was not found in module.", + ErrorType.APPLICATION, ErrorTag.UNKNOWN_ELEMENT ); } - else { - if ((nodeBuilder instanceof EmptyNodeWrapper)) { - final EmptyNodeWrapper emptyNodeBuilder = ((EmptyNodeWrapper) nodeBuilder); - if ((schema instanceof LeafSchemaNode)) { - emptyNodeBuilder.setComposite(false); - } - else { - if ((schema instanceof ContainerSchemaNode)) { - // FIXME: Add presence check - emptyNodeBuilder.setComposite(true); - } + } + + if ((schema instanceof ListSchemaNode)) { + ListSchemaNode listSchemaNode = (ListSchemaNode)schema; + final List listKeys = listSchemaNode.getKeyDefinition(); + for (final QName listKey : listKeys) { + boolean foundKey = false; + for (final NodeWrapper child : children) { + if (Objects.equal(child.unwrap().getNodeType().getLocalName(), listKey.getLocalName())) { + foundKey = true; } } + + if (!foundKey) { + throw new RestconfDocumentedException( + "Missing key in URI \"" + listKey.getLocalName() + + "\" of list \"" + listSchemaNode.getQName().getLocalName() + "\"", + ErrorType.PROTOCOL, ErrorTag.INVALID_VALUE ); + } } } } @@ -1237,6 +1268,9 @@ public class RestconfImpl implements RestconfService { else if (node instanceof LeafSchemaNode) { return _typeDefinition((LeafSchemaNode)node); } + else if (node instanceof AnyXmlSchemaNode) { + return null; + } else { throw new IllegalArgumentException("Unhandled parameter types: " + Arrays.asList(node).toString()); diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/CnSnToJsonBasicDataTypesTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/CnSnToJsonBasicDataTypesTest.java index 1ec7253b8d..93d32a1499 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/CnSnToJsonBasicDataTypesTest.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/cnsn/to/json/test/CnSnToJsonBasicDataTypesTest.java @@ -116,6 +116,75 @@ public class CnSnToJsonBasicDataTypesTest extends YangAndXmlAndDataSchemaLoader } + static class ComplexAnyXmlVerifier extends LeafVerifier { + + ComplexAnyXmlVerifier() { + super( null, JsonToken.BEGIN_OBJECT ); + } + + @Override + void verify( JsonReader reader, String keyName ) throws IOException { + + reader.beginObject(); + String innerKey = reader.nextName(); + assertEquals( "Json reader child key for " + keyName, "data", innerKey ); + assertEquals( "Json token type for key " + innerKey, JsonToken.BEGIN_OBJECT, reader.peek() ); + + reader.beginObject(); + verifyLeaf( reader, innerKey, "leaf1", "leaf1-value" ); + verifyLeaf( reader, innerKey, "leaf2", "leaf2-value" ); + + String nextName = reader.nextName(); + assertEquals( "Json reader child key for " + innerKey, "leaf-list", nextName ); + reader.beginArray(); + assertEquals( "Json value for key " + nextName, "leaf-list-value1", reader.nextString() ); + assertEquals( "Json value for key " + nextName, "leaf-list-value2", reader.nextString() ); + reader.endArray(); + + nextName = reader.nextName(); + assertEquals( "Json reader child key for " + innerKey, "list", nextName ); + reader.beginArray(); + verifyNestedLists( reader, 1 ); + verifyNestedLists( reader, 3 ); + reader.endArray(); + + reader.endObject(); + reader.endObject(); + } + + void verifyNestedLists( JsonReader reader, int leafNum ) throws IOException { + reader.beginObject(); + + String nextName = reader.nextName(); + assertEquals( "Json reader next name", "nested-list", nextName ); + + reader.beginArray(); + + reader.beginObject(); + verifyLeaf( reader, "nested-list", "nested-leaf", "nested-value" + leafNum++ ); + reader.endObject(); + + reader.beginObject(); + verifyLeaf( reader, "nested-list", "nested-leaf", "nested-value" + leafNum ); + reader.endObject(); + + reader.endArray(); + reader.endObject(); + } + + void verifyLeaf( JsonReader reader, String parent, String name, String value ) throws IOException { + String nextName = reader.nextName(); + assertEquals( "Json reader child key for " + parent, name, nextName ); + assertEquals( "Json token type for key " + parent, JsonToken.STRING, reader.peek() ); + assertEquals( "Json value for key " + nextName, value, reader.nextString() ); + } + + @Override + Object getActualValue( JsonReader reader ) throws IOException { + return null; + } + } + @BeforeClass public static void initialize() { dataLoad("/cnsn-to-json/simple-data-types"); @@ -208,6 +277,9 @@ public class CnSnToJsonBasicDataTypesTest extends YangAndXmlAndDataSchemaLoader expectedMap.put( "lfunion14", new StringVerifier( "zero" ) ); expectedMap.put( "lfempty", new EmptyVerifier() ); expectedMap.put( "identityref1", new StringVerifier( "simple-data-types:iden" ) ); + expectedMap.put( "complex-any", new ComplexAnyXmlVerifier() ); + expectedMap.put( "simple-any", new StringVerifier( "simple" ) ); + expectedMap.put( "empty-any", new StringVerifier( "" ) ); while (jReader.hasNext()) { String keyName = jReader.nextName(); diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestconfDocumentedExceptionMapperTest.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestconfDocumentedExceptionMapperTest.java index e146cf8f4f..c5c4596189 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestconfDocumentedExceptionMapperTest.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestconfDocumentedExceptionMapperTest.java @@ -9,6 +9,7 @@ package org.opendaylight.controller.sal.restconf.impl.test; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -18,6 +19,12 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.when; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import com.google.common.io.ByteStreams; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -29,7 +36,8 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; - +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javax.ws.rs.core.Application; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; @@ -41,7 +49,6 @@ import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathFactory; - import org.glassfish.jersey.server.ResourceConfig; import org.glassfish.jersey.test.JerseyTest; import org.junit.Before; @@ -63,13 +70,6 @@ import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Maps; -import com.google.common.io.ByteStreams; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; - /** * Unit tests for RestconfDocumentedExceptionMapper. * @@ -842,6 +842,14 @@ public class RestconfDocumentedExceptionMapperTest extends JerseyTest { errorListEntrySet.iterator().next().getKey() ); assertTrue( "\"error\" Json element is not an Array", errorListElement.isJsonArray() ); + // As a final check, make sure there aren't multiple "error" array elements. Unfortunately, + // the call above to getAsJsonObject().entrySet() will out duplicate "error" elements. So + // we'll use regex on the json string to verify this. + + Matcher matcher = Pattern.compile( "\"error\"[ ]*:[ ]*\\[", Pattern.DOTALL ).matcher( bos.toString() ); + assertTrue( "Expected 1 \"error\" element", matcher.find() ); + assertFalse( "Found multiple \"error\" elements", matcher.find() ); + return errorListElement.getAsJsonArray(); } @@ -850,7 +858,6 @@ public class RestconfDocumentedExceptionMapperTest extends JerseyTest { final ErrorInfoVerifier errorInfoVerifier ) { JsonElement errorInfoElement = null; - Map actualErrorInfo = null; Map leafMap = Maps.newHashMap(); for( Entry entry: errorEntryElement.getAsJsonObject().entrySet() ) { String leafName = entry.getKey(); diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/structures/LstItem.java b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/structures/LstItem.java index 9b382d210e..3617ed9fb0 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/structures/LstItem.java +++ b/opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/structures/LstItem.java @@ -7,6 +7,7 @@ */ package org.opendaylight.controller.sal.restconf.impl.test.structures; +import static org.junit.Assert.assertFalse; import java.util.HashMap; import java.util.Map; @@ -56,10 +57,14 @@ public class LstItem { } public void addLfLst(LfLst lfLst) { + assertFalse( "Found multiple leaf list elements for " + lfLst.getName(), + lfLsts.containsKey( lfLst.getName() ) ); lfLsts.put(lfLst.getName(), lfLst); } public void addLst(Lst lst) { + assertFalse( "Found multiple list elements for " + lst.getName(), + lsts.containsKey( lst.getName() ) ); lsts.put(lst.getName(), lst); } diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/simple-data-types/simple-data-types.yang b/opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/simple-data-types/simple-data-types.yang index 9bdea81579..cf6e513b30 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/simple-data-types/simple-data-types.yang +++ b/opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/simple-data-types/simple-data-types.yang @@ -269,6 +269,10 @@ module simple-data-types { } } - + anyxml complex-any; + + anyxml simple-any; + + anyxml empty-any; } } \ No newline at end of file diff --git a/opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/simple-data-types/xml/data.xml b/opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/simple-data-types/xml/data.xml index 28d355dbab..ed02ca35f6 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/simple-data-types/xml/data.xml +++ b/opendaylight/md-sal/sal-rest-connector/src/test/resources/cnsn-to-json/simple-data-types/xml/data.xml @@ -23,7 +23,6 @@ enum3 bit3 bit2 ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz - 324 33.3 55 @@ -38,5 +37,35 @@ false b1 zero + x:iden - \ No newline at end of file + + + leaf1-value + leaf2-value + + leaf-list-value1 + leaf-list-value2 + + + + nested-value1 + + + nested-value2 + + + + + + nested-value3 + + + nested-value4 + + + + + simple + + diff --git a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/DataPacketMuxDemux.java b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/DataPacketMuxDemux.java index 5c2af6d8b4..54d5fb888a 100644 --- a/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/DataPacketMuxDemux.java +++ b/opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/DataPacketMuxDemux.java @@ -32,11 +32,15 @@ import org.opendaylight.controller.sal.core.Node; import org.opendaylight.controller.sal.core.NodeConnector; import org.opendaylight.controller.sal.core.Property; import org.opendaylight.controller.sal.core.UpdateType; +import org.opendaylight.controller.sal.match.Match; +import org.opendaylight.controller.sal.packet.Ethernet; import org.opendaylight.controller.sal.packet.IPluginOutDataPacketService; +import org.opendaylight.controller.sal.packet.PacketException; import org.opendaylight.controller.sal.packet.PacketResult; import org.opendaylight.controller.sal.packet.RawPacket; import org.opendaylight.controller.sal.utils.GlobalConstants; import org.opendaylight.controller.sal.utils.HexEncode; +import org.opendaylight.controller.sal.utils.NetUtils; import org.openflow.protocol.OFMessage; import org.openflow.protocol.OFPacketIn; import org.openflow.protocol.OFPacketOut; @@ -169,12 +173,10 @@ public class DataPacketMuxDemux implements IContainerListener, @Override public void receive(ISwitch sw, OFMessage msg) { - if (sw == null || msg == null - || this.pluginOutDataPacketServices == null) { + if (sw == null || msg == null || this.pluginOutDataPacketServices == null) { // Something fishy, we cannot do anything - logger.debug( - "sw: {} and/or msg: {} and/or pluginOutDataPacketServices: {} is null!", - new Object[] { sw, msg, this.pluginOutDataPacketServices }); + logger.debug("sw: {} and/or msg: {} and/or pluginOutDataPacketServices: {} is null!", new Object[] { sw, + msg, this.pluginOutDataPacketServices }); return; } @@ -185,8 +187,7 @@ public class DataPacketMuxDemux implements IContainerListener, logger.debug("Connection service refused DataPacketMuxDemux receive {} {}", sw, msg); return; } - } - catch (Exception e) { + } catch (Exception e) { return; } @@ -204,30 +205,22 @@ public class DataPacketMuxDemux implements IContainerListener, // pass the parsed packet simply because once the // packet infra is settled all the packets will passed // around as parsed and read-only - for (int i = 0; i < this.iDataPacketListen.size(); i++) { - IDataPacketListen s = this.iDataPacketListen.get(i); - if (s.receiveDataPacket(dataPacket).equals( - PacketResult.CONSUME)) { + for (IDataPacketListen s : this.iDataPacketListen) { + if (s.receiveDataPacket(dataPacket).equals(PacketResult.CONSUME)) { logger.trace("Consumed locally data packet"); return; } } - // Now dispatch the packet toward SAL at least for - // default container, we need to revisit this in a general - // slicing architecture refresh + // Now dispatch the packet toward SAL for default container IPluginOutDataPacketService defaultOutService = this.pluginOutDataPacketServices .get(GlobalConstants.DEFAULT.toString()); if (defaultOutService != null) { defaultOutService.receiveDataPacket(dataPacket); if (logger.isTraceEnabled()) { - logger.trace( - "Dispatched to apps a frame of size: {} on " + - "container: {}: {}", new Object[] { - ofPacket.getPacketData().length, - GlobalConstants.DEFAULT.toString(), - HexEncode.bytesToHexString(dataPacket - .getPacketData()) }); + logger.trace("Dispatched to apps a frame of size: {} on " + "container: {}: {}", + new Object[] { ofPacket.getPacketData().length, GlobalConstants.DEFAULT.toString(), + HexEncode.bytesToHexString(dataPacket.getPacketData()) }); } } // Now check the mapping between nodeConnector and @@ -235,32 +228,43 @@ public class DataPacketMuxDemux implements IContainerListener, // flowSpec List containersRX = this.nc2Container.get(p); if (containersRX != null) { - for (int i = 0; i < containersRX.size(); i++) { - String container = containersRX.get(i); - IPluginOutDataPacketService s = this.pluginOutDataPacketServices - .get(container); - if (s != null) { - // TODO add filtering on a per-flowSpec base - s.receiveDataPacket(dataPacket); - if (logger.isTraceEnabled()) { - logger.trace( - "Dispatched to apps a frame of size: {}" + - " on container: {}: {}", new Object[] { - ofPacket.getPacketData().length, - container, - HexEncode.bytesToHexString(dataPacket - .getPacketData()) }); + Ethernet frame = new Ethernet(); + byte data[] = dataPacket.getPacketData(); + frame.deserialize(data, 0, data.length * NetUtils.NumBitsInAByte); + Match packetMatch = frame.getMatch(); + for (String container : containersRX) { + boolean notify = true; + List containerFlows = this.container2FlowSpecs.get(container); + if (containerFlows != null) { + notify = false; + for (ContainerFlow cFlow : containerFlows) { + if (cFlow.allowsMatch(packetMatch)) { + notify = true; + break; + } + } + if (notify) { + IPluginOutDataPacketService s = this.pluginOutDataPacketServices.get(container); + if (s != null) { + s.receiveDataPacket(dataPacket); + if (logger.isTraceEnabled()) { + logger.trace( + "Dispatched to apps a frame of size: {}" + " on container: {}: {}", + new Object[] { ofPacket.getPacketData().length, container, + HexEncode.bytesToHexString(dataPacket.getPacketData()) }); + } + } } } } } - // This is supposed to be the catch all for all the // DataPacket hence we will assume it has been handled return; } catch (ConstructionException cex) { + } catch (PacketException e) { + logger.debug("Failed to deserialize raw packet: ", e.getMessage()); } - // If we reach this point something went wrong. return; } else { diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/ARP.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/ARP.java index 8fc0d625eb..21c17b366c 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/ARP.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/ARP.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * Copyright (c) 2013-2014 Cisco Systems, Inc. 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, @@ -258,18 +258,23 @@ public class ARP extends Packet { @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (!super.equals(obj)) + } + if (!super.equals(obj)) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } ARP other = (ARP) obj; if (fieldValues == null) { - if (other.fieldValues != null) + if (other.fieldValues != null) { return false; - } else if (!fieldValues.equals(other.fieldValues)) + } + } else if (!fieldValues.equals(other.fieldValues)) { return false; + } return true; } } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/Ethernet.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/Ethernet.java index d0068564a9..235e71a760 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/Ethernet.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/Ethernet.java @@ -15,6 +15,8 @@ import java.util.Map; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; +import org.opendaylight.controller.sal.match.Match; +import org.opendaylight.controller.sal.match.MatchType; import org.opendaylight.controller.sal.utils.EtherTypes; import org.opendaylight.controller.sal.utils.NetUtils; @@ -139,4 +141,10 @@ public class Ethernet extends Packet { return this; } + @Override + public void populateMatch(Match match) { + match.setField(MatchType.DL_SRC, this.getSourceMACAddress()); + match.setField(MatchType.DL_DST, this.getDestinationMACAddress()); + match.setField(MatchType.DL_TYPE, this.getEtherType()); + } } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/IEEE8021Q.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/IEEE8021Q.java index 39c7d386bc..9825d0eefb 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/IEEE8021Q.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/IEEE8021Q.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * Copyright (c) 2013-2014 Cisco Systems, Inc. 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, @@ -13,6 +13,8 @@ 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.sal.match.Match; +import org.opendaylight.controller.sal.match.MatchType; /** * Class that represents the IEEE 802.1Q objects @@ -148,4 +150,10 @@ public class IEEE8021Q extends Packet { return this; } + @Override + public void populateMatch(Match match) { + match.setField(MatchType.DL_VLAN, this.getVid()); + match.setField(MatchType.DL_VLAN_PR, this.getPcp()); + match.setField(MatchType.DL_TYPE, this.getEtherType()); + } } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/IPv4.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/IPv4.java index 559acd633a..3363f423d6 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/IPv4.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/IPv4.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * Copyright (c) 2013-2014 Cisco Systems, Inc. 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, @@ -20,6 +20,8 @@ import java.util.Random; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; +import org.opendaylight.controller.sal.match.Match; +import org.opendaylight.controller.sal.match.MatchType; import org.opendaylight.controller.sal.utils.IPProtocols; import org.opendaylight.controller.sal.utils.NetUtils; import org.slf4j.Logger; @@ -577,4 +579,12 @@ public class IPv4 extends Packet { corrupted = true; } } + + @Override + public void populateMatch(Match match) { + match.setField(MatchType.NW_SRC, NetUtils.getInetAddress(this.getSourceAddress())); + match.setField(MatchType.NW_DST, NetUtils.getInetAddress(this.getDestinationAddress())); + match.setField(MatchType.NW_PROTO, this.getProtocol()); + match.setField(MatchType.NW_TOS, this.getDiffServ()); + } } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/LLDP.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/LLDP.java index 6f5cf04a52..9b5dc082bb 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/LLDP.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/LLDP.java @@ -12,6 +12,7 @@ import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; + import org.opendaylight.controller.sal.utils.HexEncode; import org.opendaylight.controller.sal.utils.NetUtils; diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/LLDPTLV.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/LLDPTLV.java index efb938e37f..35244ea697 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/LLDPTLV.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/LLDPTLV.java @@ -151,18 +151,23 @@ public class LLDPTLV extends Packet { @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (!super.equals(obj)) + } + if (!super.equals(obj)) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } LLDPTLV other = (LLDPTLV) obj; if (fieldValues == null) { - if (other.fieldValues != null) + if (other.fieldValues != null) { return false; - } else if (!fieldValues.equals(other.fieldValues)) + } + } else if (!fieldValues.equals(other.fieldValues)) { return false; + } return true; } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/Packet.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/Packet.java index 58b5d3914a..789aa12653 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/Packet.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/Packet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * Copyright (c) 2013-2014 Cisco Systems, Inc. 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, @@ -13,6 +13,7 @@ import java.util.Map; import java.util.Map.Entry; import org.apache.commons.lang3.tuple.Pair; +import org.opendaylight.controller.sal.match.Match; import org.opendaylight.controller.sal.utils.HexEncode; import org.opendaylight.controller.sal.utils.NetUtils; import org.slf4j.Logger; @@ -364,4 +365,31 @@ public abstract class Packet { return true; } + /** + * Adds to the passed Match this packet's header fields + * + * @param match + * The Match object to populate + */ + public void populateMatch(Match match) { + // To be overridden by derived packet classes which have well known + // header fields so that Packet.getMatch would return desired result + } + + /** + * Returns the Match object containing this packet and its payload + * encapsulated packets' header fields + * + * @return The Match containing the header fields of this packet and of its + * payload encapsulated packets + */ + public Match getMatch() { + Match match = new Match(); + Packet packet = this; + while (packet != null) { + packet.populateMatch(match); + packet = packet.getPayload(); + } + return match; + } } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/TCP.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/TCP.java index 8253ac46d3..d27494599c 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/TCP.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/TCP.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * Copyright (c) 2013-2014 Cisco Systems, Inc. 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, @@ -15,6 +15,8 @@ import java.util.Map; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; +import org.opendaylight.controller.sal.match.Match; +import org.opendaylight.controller.sal.match.MatchType; /** * Class that represents the TCP segment objects @@ -238,4 +240,9 @@ public class TCP extends Packet { return (BitBufferHelper.getShort(fieldValues.get(CHECKSUM))); } + @Override + public void populateMatch(Match match) { + match.setField(MatchType.TP_SRC, this.getSourcePort()); + match.setField(MatchType.TP_DST, this.getDestinationPort()); + } } diff --git a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/UDP.java b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/UDP.java index f82ed8fcae..069a277f89 100644 --- a/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/UDP.java +++ b/opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/UDP.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * Copyright (c) 2013-2014 Cisco Systems, Inc. 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, @@ -15,6 +15,8 @@ import java.util.Map; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; +import org.opendaylight.controller.sal.match.Match; +import org.opendaylight.controller.sal.match.MatchType; /** * Class that represents the UDP datagram objects @@ -156,4 +158,10 @@ public class UDP extends Packet { fieldValues.put(CHECKSUM, checksum); return this; } + + @Override + public void populateMatch(Match match) { + match.setField(MatchType.TP_SRC, this.getSourcePort()); + match.setField(MatchType.TP_DST, this.getDestinationPort()); + } } diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/ARPTest.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/ARPTest.java index a3ebd7ee0d..10bd535eb2 100644 --- a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/ARPTest.java +++ b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/ARPTest.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * Copyright (c) 2013-2014 Cisco Systems, Inc. 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, diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/EthernetTest.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/EthernetTest.java index 2494eb6b2d..494dd2abf2 100644 --- a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/EthernetTest.java +++ b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/EthernetTest.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * Copyright (c) 2013-2014 Cisco Systems, Inc. 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, @@ -9,9 +9,14 @@ package org.opendaylight.controller.sal.packet; +import java.util.Arrays; + import junit.framework.Assert; import org.junit.Test; +import org.opendaylight.controller.sal.match.Match; +import org.opendaylight.controller.sal.match.MatchType; +import org.opendaylight.controller.sal.utils.EtherTypes; public class EthernetTest { @@ -95,4 +100,22 @@ public class EthernetTest { } + @Test + public void testGetMatch() throws Exception { + Ethernet eth = new Ethernet(); + byte smac[] = { (byte) 0xf0, (byte) 0xde, (byte) 0xf1, (byte) 0x71, (byte) 0x72, (byte) 0x8d }; + byte dmac[] = { (byte) 0xde, (byte) 0x28, (byte) 0xdb, (byte) 0xb3, (byte) 0x7c, (byte) 0xf8 }; + short ethType = EtherTypes.IPv4.shortValue(); + eth.setDestinationMACAddress(dmac); + eth.setSourceMACAddress(smac); + eth.setEtherType(ethType); + + Match match = eth.getMatch(); + + Assert.assertTrue(Arrays.equals(smac, (byte[]) match.getField(MatchType.DL_SRC).getValue())); + Assert.assertTrue(Arrays.equals(dmac, (byte[]) match.getField(MatchType.DL_DST).getValue())); + Assert.assertEquals(ethType, (short) match.getField(MatchType.DL_TYPE).getValue()); + + } + } diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/IEEE8021QTest.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/IEEE8021QTest.java index a4c6c1fc4b..2443b491c7 100644 --- a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/IEEE8021QTest.java +++ b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/IEEE8021QTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * Copyright (c) 2013-2014 Cisco Systems, Inc. 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, @@ -9,7 +9,11 @@ package org.opendaylight.controller.sal.packet; import junit.framework.Assert; + import org.junit.Test; +import org.opendaylight.controller.sal.match.Match; +import org.opendaylight.controller.sal.match.MatchType; +import org.opendaylight.controller.sal.utils.EtherTypes; import org.opendaylight.controller.sal.utils.NetUtils; public class IEEE8021QTest { @@ -212,4 +216,21 @@ public class IEEE8021QTest { Assert.assertTrue(data[44] == (byte) 0x09); Assert.assertTrue(data[45] == (byte) 0xFE); } + + @Test + public void testGetMatchFullPacket() throws Exception { + IEEE8021Q dot1q = new IEEE8021Q(); + byte priority = 4; + short vlanId = 59; + short ethType = EtherTypes.IPv4.shortValue(); + dot1q.setPcp(priority); + dot1q.setVid(vlanId); + dot1q.setEtherType(ethType); + + Match match = dot1q.getMatch(); + + Assert.assertEquals(priority, (byte) match.getField(MatchType.DL_VLAN_PR).getValue()); + Assert.assertEquals(vlanId, (short) match.getField(MatchType.DL_VLAN).getValue()); + Assert.assertEquals(ethType, (short) match.getField(MatchType.DL_TYPE).getValue()); + } } diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/IPv4Test.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/IPv4Test.java index 5afcd8be7d..f5298711b6 100644 --- a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/IPv4Test.java +++ b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/IPv4Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * Copyright (c) 2013-2014 Cisco Systems, Inc. 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, @@ -15,6 +15,8 @@ import java.util.Arrays; import junit.framework.Assert; import org.junit.Test; +import org.opendaylight.controller.sal.match.Match; +import org.opendaylight.controller.sal.match.MatchType; import org.opendaylight.controller.sal.utils.EtherTypes; import org.opendaylight.controller.sal.utils.IPProtocols; import org.opendaylight.controller.sal.utils.NetUtils; @@ -452,4 +454,31 @@ public class IPv4Test { Assert.assertFalse(decIcmp.isCorrupted()); Assert.assertTrue(Arrays.equals(icmpRawPayload, decIcmp.getRawPayload())); } + + @Test + public void testGetMatch() throws Exception { + IPv4 ip = new IPv4(); + InetAddress sourceAddress = InetAddress.getByName("172.168.190.15"); + InetAddress destintationAddress = InetAddress.getByName("23.128.0.11"); + byte protocol = IPProtocols.TCP.byteValue(); + byte tos = 7; + ip.setVersion((byte) 4); + ip.setIdentification((short) 5); + ip.setDiffServ(tos); + ip.setECN((byte) 0); + ip.setTotalLength((short) 84); + ip.setFlags((byte) 2); + ip.setFragmentOffset((short) 0); + ip.setTtl((byte) 64); + ip.setProtocol(protocol); + ip.setDestinationAddress(destintationAddress); + ip.setSourceAddress(sourceAddress); + + Match match = ip.getMatch(); + + Assert.assertEquals(sourceAddress, match.getField(MatchType.NW_SRC).getValue()); + Assert.assertEquals(destintationAddress, match.getField(MatchType.NW_DST).getValue()); + Assert.assertEquals(protocol, (byte) match.getField(MatchType.NW_PROTO).getValue()); + Assert.assertEquals(tos, (byte) match.getField(MatchType.NW_TOS).getValue()); + } } diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/PacketTest.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/PacketTest.java index 8f3b283b2e..95eff32ef1 100644 --- a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/PacketTest.java +++ b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/PacketTest.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * Copyright (c) 2013-2014 Cisco Systems, Inc. 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, @@ -9,11 +9,17 @@ package org.opendaylight.controller.sal.packet; +import java.net.InetAddress; +import java.util.Arrays; import java.util.Map; import junit.framework.Assert; import org.junit.Test; +import org.opendaylight.controller.sal.match.Match; +import org.opendaylight.controller.sal.match.MatchType; +import org.opendaylight.controller.sal.utils.EtherTypes; +import org.opendaylight.controller.sal.utils.IPProtocols; public class PacketTest { @@ -120,9 +126,9 @@ public class PacketTest { eth.setSourceMACAddress(sMAC); eth.setEtherType(etherType); - dMACdata = (byte[]) fCValues.get("DestinationMACAddress"); - sMACdata = (byte[]) fCValues.get("SourceMACAddress"); - etherTypedata = (byte[]) fCValues.get("EtherType"); + dMACdata = fCValues.get("DestinationMACAddress"); + sMACdata = fCValues.get("SourceMACAddress"); + etherTypedata = fCValues.get("EtherType"); Assert.assertTrue(dMACdata[0] == 10); Assert.assertTrue(dMACdata[1] == 12); @@ -160,4 +166,62 @@ public class PacketTest { Assert.assertTrue(data[13] == 6); } + + @Test + public void testGetMatch() throws Exception { + TCP tcp = new TCP(); + short sport = (short) 11093; + short dport = (short) 23; + tcp.setSourcePort(sport); + tcp.setDestinationPort(dport); + + IPv4 ip = new IPv4(); + InetAddress sourceAddress = InetAddress.getByName("192.168.100.100"); + InetAddress destintationAddress = InetAddress.getByName("192.168.100.101"); + byte protocol = IPProtocols.TCP.byteValue(); + byte tos = 5; + ip.setVersion((byte) 4); + ip.setIdentification((short) 5); + ip.setDiffServ(tos); + ip.setECN((byte) 0); + ip.setTotalLength((short) 84); + ip.setFlags((byte) 2); + ip.setFragmentOffset((short) 0); + ip.setTtl((byte) 64); + ip.setProtocol(protocol); + ip.setDestinationAddress(destintationAddress); + ip.setSourceAddress(sourceAddress); + ip.setPayload(tcp); + + IEEE8021Q dot1q = new IEEE8021Q(); + byte priority = 4; + short vlanId = 59; + short ethType = EtherTypes.IPv4.shortValue(); + dot1q.setPcp(priority); + dot1q.setVid(vlanId); + dot1q.setEtherType(ethType); + dot1q.setPayload(ip); + + Ethernet eth = new Ethernet(); + byte smac[] = { (byte) 0xf0, (byte) 0xde, (byte) 0xf1, (byte) 0x71, (byte) 0x72, (byte) 0x8d }; + byte dmac[] = { (byte) 0xde, (byte) 0x28, (byte) 0xdb, (byte) 0xb3, (byte) 0x7c, (byte) 0xf8 }; + eth.setDestinationMACAddress(dmac); + eth.setSourceMACAddress(smac); + eth.setEtherType(EtherTypes.VLANTAGGED.shortValue()); + eth.setPayload(dot1q); + + Match match = eth.getMatch(); + + Assert.assertTrue(Arrays.equals(smac, (byte[]) match.getField(MatchType.DL_SRC).getValue())); + Assert.assertTrue(Arrays.equals(dmac, (byte[]) match.getField(MatchType.DL_DST).getValue())); + Assert.assertEquals(priority, (byte) match.getField(MatchType.DL_VLAN_PR).getValue()); + Assert.assertEquals(vlanId, (short) match.getField(MatchType.DL_VLAN).getValue()); + Assert.assertEquals(ethType, (short) match.getField(MatchType.DL_TYPE).getValue()); + Assert.assertEquals(sourceAddress, match.getField(MatchType.NW_SRC).getValue()); + Assert.assertEquals(destintationAddress, match.getField(MatchType.NW_DST).getValue()); + Assert.assertEquals(protocol, (byte) match.getField(MatchType.NW_PROTO).getValue()); + Assert.assertEquals(tos, (byte) match.getField(MatchType.NW_TOS).getValue()); + Assert.assertEquals(sport, (short) match.getField(MatchType.TP_SRC).getValue()); + Assert.assertEquals(dport, (short) match.getField(MatchType.TP_DST).getValue()); + } } diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/TCPTest.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/TCPTest.java index 3e18aedfdb..e56f41e5c1 100644 --- a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/TCPTest.java +++ b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/TCPTest.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * Copyright (c) 2013-2014 Cisco Systems, Inc. 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, @@ -12,6 +12,8 @@ package org.opendaylight.controller.sal.packet; import junit.framework.Assert; import org.junit.Test; +import org.opendaylight.controller.sal.match.Match; +import org.opendaylight.controller.sal.match.MatchType; public class TCPTest { @@ -113,4 +115,18 @@ public class TCPTest { short checksum = tcp.getChecksum(); Assert.assertTrue(checksum == 200); } + + @Test + public void testGetMatch() throws Exception { + TCP tcp = new TCP(); + short sport = (short) 52012; + short dport = (short) 40345; + tcp.setSourcePort(sport); + tcp.setDestinationPort(dport); + + Match match = tcp.getMatch(); + + Assert.assertEquals(sport, (short) match.getField(MatchType.TP_SRC).getValue()); + Assert.assertEquals(dport, (short) match.getField(MatchType.TP_DST).getValue()); + } } diff --git a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/UDPTest.java b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/UDPTest.java index 8d5be849a0..a3a597a82d 100644 --- a/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/UDPTest.java +++ b/opendaylight/sal/api/src/test/java/org/opendaylight/controller/sal/packet/UDPTest.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * Copyright (c) 2013-2014 Cisco Systems, Inc. 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, @@ -12,6 +12,8 @@ package org.opendaylight.controller.sal.packet; import junit.framework.Assert; import org.junit.Test; +import org.opendaylight.controller.sal.match.Match; +import org.opendaylight.controller.sal.match.MatchType; public class UDPTest { @@ -95,4 +97,19 @@ public class UDPTest { } + @Test + public void testGetMatch() throws Exception { + UDP udp = new UDP(); + short sport = (short) 33000; + short dport = (short) 843; + udp.setSourcePort(sport); + udp.setDestinationPort(dport); + + Match match = udp.getMatch(); + + Assert.assertEquals(sport, (short) match.getField(MatchType.TP_SRC).getValue()); + Assert.assertEquals(dport, (short) match.getField(MatchType.TP_DST).getValue()); + + } + }