<dependencies>
<!-- project specific dependencies -->
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>ietf-yang-types-20130715</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>ietf-inet-types-2013-07-15</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>yang-ext</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>iana-if-type-2014-05-08</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.model</groupId>
+ <artifactId>ietf-interfaces</artifactId>
+ </dependency>
<!-- testing dependencies -->
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<instructions>
<Export-Package>
org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.*
- </Export-Package> -->
+ </Export-Package>
</instructions>
</configuration>
</plugin>
--- /dev/null
+/*\r
+ * Copyright (c) 2016 Cisco Systems. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+\r
+package org.opendaylight.groupbasedpolicy.renderer.vpp.commands;\r
+\r
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General;\r
+\r
+public abstract class AbstractInterfaceCommand<T extends AbstractInterfaceCommand<T>> implements ConfigCommand {\r
+\r
+ protected General.Operations operation;\r
+ protected String name;\r
+ protected String description;\r
+ protected Boolean enabled;\r
+\r
+ protected enum linkUpDownTrap {\r
+ ENABLED, DISABLED\r
+ }\r
+\r
+ public General.Operations getOperation() {\r
+ return operation;\r
+ }\r
+\r
+ public String getName() {\r
+ return name;\r
+ }\r
+\r
+ public String getDescription() {\r
+ return description;\r
+ }\r
+\r
+ public AbstractInterfaceCommand<T> setDescription(String description) {\r
+ this.description = description;\r
+ return this;\r
+ }\r
+\r
+ public Boolean getEnabled() {\r
+ return enabled;\r
+ }\r
+\r
+ public AbstractInterfaceCommand<T> setEnabled(Boolean enabled) {\r
+ this.enabled = enabled;\r
+ return this;\r
+ }\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (c) 2016 Cisco Systems. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+\r
+package org.opendaylight.groupbasedpolicy.renderer.vpp.commands;\r
+\r
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;\r
+\r
+public interface ConfigCommand {\r
+\r
+ /**\r
+ * Execute command using a given data modification transaction\r
+ *\r
+ * @param readWriteTransaction Transaction for command execution\r
+ */\r
+ void execute(ReadWriteTransaction readWriteTransaction);\r
+\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (c) 2016 Cisco Systems. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+\r
+package org.opendaylight.groupbasedpolicy.renderer.vpp.commands;\r
+\r
+import com.google.common.base.Preconditions;\r
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;\r
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;\r
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General;\r
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VhostUserRole;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentation;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentationBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.L2Builder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.VhostUserBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.l2.interconnection.BridgeBasedBuilder;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+\r
+public class VhostUserCommand extends AbstractInterfaceCommand {\r
+\r
+ private static final Logger LOG = LoggerFactory.getLogger(VhostUserCommand.class);\r
+ private String socket;\r
+ private VhostUserRole role;\r
+ private String bridgeDomain;\r
+\r
+ private VhostUserCommand(VhostUserCommandBuilder builder) {\r
+ this.name = builder.getName();\r
+ this.operation = builder.getOperation();\r
+ this.socket = builder.getSocket();\r
+ this.role = builder.getRole();\r
+ this.enabled = builder.isEnabled();\r
+ this.description = builder.getDescription();\r
+ this.bridgeDomain = builder.getBridgeDomain();\r
+\r
+ }\r
+\r
+ public static VhostUserCommandBuilder builder() {\r
+ return new VhostUserCommandBuilder();\r
+ }\r
+\r
+ public String getSocket() {\r
+ return socket;\r
+ }\r
+\r
+ public VhostUserRole getRole() {\r
+ return role;\r
+ }\r
+\r
+ public String getBridgeDomain() {\r
+ return bridgeDomain;\r
+ }\r
+\r
+ @Override\r
+ public void execute(ReadWriteTransaction readWriteTransaction) {\r
+ switch (getOperation()) {\r
+\r
+ case PUT:\r
+ LOG.info("Executing Add operation for command: {}", this);\r
+ put(readWriteTransaction);\r
+ break;\r
+ case DELETE:\r
+ LOG.info("Executing Delete operation for command: {}", this);\r
+ delete(readWriteTransaction);\r
+ break;\r
+ case MERGE:\r
+ LOG.info("Executing Update operation for command: {}", this);\r
+ merge(readWriteTransaction);\r
+ break;\r
+ default:\r
+ LOG.error("Execution failed for command: {}", this);\r
+ break;\r
+ }\r
+ }\r
+\r
+ private void put(ReadWriteTransaction readWriteTransaction) {\r
+ Preconditions.checkNotNull(name, "Interface name should not be null");\r
+\r
+ InterfaceBuilder interfaceBuilder = getVhostUserInterfaceBuilder();\r
+\r
+ readWriteTransaction.put(LogicalDatastoreType.CONFIGURATION,\r
+ VppIidFactory.getInterfaceIID(interfaceBuilder.getKey()), interfaceBuilder.build(), true);\r
+ }\r
+\r
+ private void merge(ReadWriteTransaction readWriteTransaction) {\r
+ Preconditions.checkNotNull(name, "Interface name should not be null");\r
+\r
+ InterfaceBuilder interfaceBuilder = getVhostUserInterfaceBuilder();\r
+\r
+ readWriteTransaction.merge(LogicalDatastoreType.CONFIGURATION,\r
+ VppIidFactory.getInterfaceIID(interfaceBuilder.getKey()), interfaceBuilder.build());\r
+ }\r
+\r
+ private InterfaceBuilder getVhostUserInterfaceBuilder() {\r
+ InterfaceBuilder interfaceBuilder =\r
+ new InterfaceBuilder().setKey(new InterfaceKey(name))\r
+ .setEnabled(enabled)\r
+ .setDescription(description)\r
+ .setType(\r
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VhostUser.class)\r
+ .setName(name)\r
+ .setLinkUpDownTrapEnable(Interface.LinkUpDownTrapEnable.Enabled);\r
+\r
+ // Create the vhost augmentation\r
+ VppInterfaceAugmentation vppAugmentation =\r
+ new VppInterfaceAugmentationBuilder()\r
+ .setVhostUser(new VhostUserBuilder().setRole(role).setSocket(socket).build())\r
+ .setL2(new L2Builder()\r
+ .setInterconnection(new BridgeBasedBuilder().setBridgeDomain(bridgeDomain).build()).build())\r
+ .build();\r
+\r
+ interfaceBuilder.addAugmentation(VppInterfaceAugmentation.class, vppAugmentation);\r
+ return interfaceBuilder;\r
+ }\r
+\r
+ private void delete(ReadWriteTransaction readWriteTransaction) {\r
+ try {\r
+ readWriteTransaction.delete(LogicalDatastoreType.CONFIGURATION,\r
+ VppIidFactory.getInterfaceIID(new InterfaceKey(name)));\r
+ } catch (IllegalStateException ex) {\r
+ LOG.debug("Vhost Interface is not present in DS", ex);\r
+ }\r
+\r
+ }\r
+\r
+ public static class VhostUserCommandBuilder {\r
+\r
+ private String name;\r
+ private General.Operations operation;\r
+ private String socket;\r
+ private VhostUserRole role = VhostUserRole.Server;\r
+ private boolean enabled = true;\r
+ private String description;\r
+ private String bridgeDomain;\r
+\r
+ public String getName() {\r
+ return name;\r
+ }\r
+\r
+ public VhostUserCommandBuilder setName(String name) {\r
+ this.name = name;\r
+ return this;\r
+ }\r
+\r
+ public General.Operations getOperation() {\r
+ return operation;\r
+ }\r
+\r
+ public VhostUserCommandBuilder setOperation(General.Operations operation) {\r
+ this.operation = operation;\r
+ return this;\r
+ }\r
+\r
+ public String getSocket() {\r
+ return socket;\r
+ }\r
+\r
+ public VhostUserCommandBuilder setSocket(String socket) {\r
+ this.socket = socket;\r
+ return this;\r
+ }\r
+\r
+ public VhostUserRole getRole() {\r
+ return role;\r
+ }\r
+\r
+ public VhostUserCommandBuilder setRole(VhostUserRole role) {\r
+ this.role = role;\r
+ return this;\r
+ }\r
+\r
+ public boolean isEnabled() {\r
+ return enabled;\r
+ }\r
+\r
+ public VhostUserCommandBuilder setEnabled(boolean enabled) {\r
+ this.enabled = enabled;\r
+ return this;\r
+ }\r
+\r
+ public String getDescription() {\r
+ return description;\r
+ }\r
+\r
+ public VhostUserCommandBuilder setDescription(String description) {\r
+ this.description = description;\r
+ return this;\r
+ }\r
+\r
+ public String getBridgeDomain() {\r
+ return bridgeDomain;\r
+ }\r
+\r
+ public VhostUserCommandBuilder setBridgeDomain(String bridgeDomain) {\r
+ this.bridgeDomain = bridgeDomain;\r
+ return this;\r
+ }\r
+\r
+ /**\r
+ * VhostUserCommand build method.\r
+ *\r
+ * @return VhostUserCommand\r
+ * @throws IllegalArgumentException if name, operation or socket is null.\r
+ */\r
+ public VhostUserCommand build() {\r
+ Preconditions.checkArgument(this.name != null);\r
+ Preconditions.checkArgument(this.operation != null);\r
+ Preconditions.checkArgument(this.socket != null);\r
+\r
+ return new VhostUserCommand(this);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (c) 2016 Cisco Systems. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+\r
+package org.opendaylight.groupbasedpolicy.renderer.vpp.util;\r
+\r
+\r
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;\r
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;\r
+import org.opendaylight.yangtools.yang.binding.DataObject;\r
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;\r
+\r
+public class General {\r
+\r
+ /**\r
+ * Operations that can be executed over ConfigCommand. Operation names reflect operations used in WriteTransaction.\r
+ * For more information on these operations, please see the documentation in:\r
+ * <br>\r
+ * {@link WriteTransaction#put(LogicalDatastoreType, InstanceIdentifier, DataObject, boolean)}<br>\r
+ * {@link WriteTransaction#merge(LogicalDatastoreType, InstanceIdentifier, DataObject, boolean)}<br>\r
+ * {@link WriteTransaction#delete(LogicalDatastoreType, InstanceIdentifier)}<br>\r
+ *\r
+ */\r
+ public enum Operations {\r
+ PUT, DELETE, MERGE\r
+ }\r
+}\r
--- /dev/null
+/*
+ * Copyright (c) 2016 Cisco Systems. 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.groupbasedpolicy.renderer.vpp.util;
+
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class VppIidFactory {
+
+ public static InstanceIdentifier<Interface> getInterfaceIID(InterfaceKey interfaceKey) {
+ return InstanceIdentifier.create(Interfaces.class).child(Interface.class, interfaceKey);
+ }
+}
--- /dev/null
+module ietf-ip {
+
+ yang-version 1;
+
+ namespace
+ "urn:ietf:params:xml:ns:yang:ietf-ip";
+
+ prefix ip;
+
+ import ietf-interfaces {
+ prefix if;
+ }
+ import ietf-inet-types {
+ prefix inet;
+ }
+ import ietf-yang-types {
+ prefix yang;
+ }
+
+ organization
+ "IETF NETMOD (NETCONF Data Modeling Language) Working Group";
+
+ contact
+ "WG Web: <http://tools.ietf.org/wg/netmod/>
+ WG List: <mailto:netmod@ietf.org>
+
+ WG Chair: Thomas Nadeau
+ <mailto:tnadeau@lucidvision.com>
+
+ WG Chair: Juergen Schoenwaelder
+ <mailto:j.schoenwaelder@jacobs-university.de>
+
+ Editor: Martin Bjorklund
+ <mailto:mbj@tail-f.com>";
+
+ description
+ "This module contains a collection of YANG definitions for
+ configuring IP implementations.
+
+ Copyright (c) 2014 IETF Trust and the persons identified as
+ authors of the code. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or
+ without modification, is permitted pursuant to, and subject
+ to the license terms contained in, the Simplified BSD License
+ set forth in Section 4.c of the IETF Trust's Legal Provisions
+ Relating to IETF Documents
+ (http://trustee.ietf.org/license-info).
+
+ This version of this YANG module is part of RFC 7277; see
+ the RFC itself for full legal notices.";
+
+ revision "2014-06-16" {
+ description "Initial revision.";
+ reference
+ "RFC 7277: A YANG Data Model for IP Management";
+
+ }
+
+
+ feature ipv4-non-contiguous-netmasks {
+ description
+ "Indicates support for configuring non-contiguous
+ subnet masks.";
+ }
+
+ feature ipv6-privacy-autoconf {
+ description
+ "Indicates support for Privacy Extensions for Stateless Address
+ Autoconfiguration in IPv6.";
+ reference
+ "RFC 4941: Privacy Extensions for Stateless Address
+ Autoconfiguration in IPv6";
+
+ }
+
+ typedef ip-address-origin {
+ type enumeration {
+ enum "other" {
+ value 0;
+ description
+ "None of the following.";
+ }
+ enum "static" {
+ value 1;
+ description
+ "Indicates that the address has been statically
+ configured - for example, using NETCONF or a Command Line
+ Interface.";
+ }
+ enum "dhcp" {
+ value 2;
+ description
+ "Indicates an address that has been assigned to this
+ system by a DHCP server.";
+ }
+ enum "link-layer" {
+ value 3;
+ description
+ "Indicates an address created by IPv6 stateless
+ autoconfiguration that embeds a link-layer address in its
+ interface identifier.";
+ }
+ enum "random" {
+ value 4;
+ description
+ "Indicates an address chosen by the system at
+
+ random, e.g., an IPv4 address within 169.254/16, an
+ RFC 4941 temporary address, or an RFC 7217 semantically
+ opaque address.";
+ reference
+ "RFC 4941: Privacy Extensions for Stateless Address
+ Autoconfiguration in IPv6
+ RFC 7217: A Method for Generating Semantically Opaque
+ Interface Identifiers with IPv6 Stateless
+ Address Autoconfiguration (SLAAC)";
+
+ }
+ }
+ description
+ "The origin of an address.";
+ }
+
+ typedef neighbor-origin {
+ type enumeration {
+ enum "other" {
+ value 0;
+ description
+ "None of the following.";
+ }
+ enum "static" {
+ value 1;
+ description
+ "Indicates that the mapping has been statically
+ configured - for example, using NETCONF or a Command Line
+ Interface.";
+ }
+ enum "dynamic" {
+ value 2;
+ description
+ "Indicates that the mapping has been dynamically resolved
+ using, e.g., IPv4 ARP or the IPv6 Neighbor Discovery
+ protocol.";
+ }
+ }
+ description
+ "The origin of a neighbor entry.";
+ }
+
+ augment /if:interfaces/if:interface {
+ description
+ "Parameters for configuring IP on interfaces.
+
+ If an interface is not capable of running IP, the server
+ must not allow the client to configure these parameters.";
+ container ipv4 {
+ presence
+ "Enables IPv4 unless the 'enabled' leaf
+ (which defaults to 'true') is set to 'false'";
+ description
+ "Parameters for the IPv4 address family.";
+ leaf enabled {
+ type boolean;
+ default 'true';
+ description
+ "Controls whether IPv4 is enabled or disabled on this
+ interface. When IPv4 is enabled, this interface is
+ connected to an IPv4 stack, and the interface can send
+ and receive IPv4 packets.";
+ }
+
+ leaf forwarding {
+ type boolean;
+ default 'false';
+ description
+ "Controls IPv4 packet forwarding of datagrams received by,
+ but not addressed to, this interface. IPv4 routers
+ forward datagrams. IPv4 hosts do not (except those
+ source-routed via the host).";
+ }
+
+ leaf mtu {
+ type uint16 {
+ range "68..max";
+ }
+ units "octets";
+ description
+ "The size, in octets, of the largest IPv4 packet that the
+ interface will send and receive.
+
+ The server may restrict the allowed values for this leaf,
+ depending on the interface's type.
+
+ If this leaf is not configured, the operationally used MTU
+ depends on the interface's type.";
+ reference
+ "RFC 791: Internet Protocol";
+
+ }
+
+ list address {
+ key "ip";
+ description
+ "The list of configured IPv4 addresses on the interface.";
+ leaf ip {
+ type inet:ipv4-address-no-zone;
+ description
+ "The IPv4 address on the interface.";
+ }
+
+ choice subnet {
+ mandatory true;
+ description
+ "The subnet can be specified as a prefix-length, or,
+ if the server supports non-contiguous netmasks, as
+ a netmask.";
+ leaf prefix-length {
+ type uint8 {
+ range "0..32";
+ }
+ description
+ "The length of the subnet prefix.";
+ }
+ leaf netmask {
+ if-feature ipv4-non-contiguous-netmasks;
+ type yang:dotted-quad;
+ description
+ "The subnet specified as a netmask.";
+ }
+ } // choice subnet
+ } // list address
+
+ list neighbor {
+ key "ip";
+ description
+ "A list of mappings from IPv4 addresses to
+ link-layer addresses.
+
+ Entries in this list are used as static entries in the
+ ARP Cache.";
+ reference
+ "RFC 826: An Ethernet Address Resolution Protocol";
+
+ leaf ip {
+ type inet:ipv4-address-no-zone;
+ description
+ "The IPv4 address of the neighbor node.";
+ }
+
+ leaf link-layer-address {
+ type yang:phys-address;
+ mandatory true;
+ description
+ "The link-layer address of the neighbor node.";
+ }
+ } // list neighbor
+ } // container ipv4
+
+ container ipv6 {
+ presence
+ "Enables IPv6 unless the 'enabled' leaf
+ (which defaults to 'true') is set to 'false'";
+ description
+ "Parameters for the IPv6 address family.";
+ leaf enabled {
+ type boolean;
+ default 'true';
+ description
+ "Controls whether IPv6 is enabled or disabled on this
+ interface. When IPv6 is enabled, this interface is
+ connected to an IPv6 stack, and the interface can send
+ and receive IPv6 packets.";
+ }
+
+ leaf forwarding {
+ type boolean;
+ default 'false';
+ description
+ "Controls IPv6 packet forwarding of datagrams received by,
+ but not addressed to, this interface. IPv6 routers
+ forward datagrams. IPv6 hosts do not (except those
+ source-routed via the host).";
+ reference
+ "RFC 4861: Neighbor Discovery for IP version 6 (IPv6)
+ Section 6.2.1, IsRouter";
+
+ }
+
+ leaf mtu {
+ type uint32 {
+ range "1280..max";
+ }
+ units "octets";
+ description
+ "The size, in octets, of the largest IPv6 packet that the
+ interface will send and receive.
+
+ The server may restrict the allowed values for this leaf,
+ depending on the interface's type.
+
+ If this leaf is not configured, the operationally used MTU
+ depends on the interface's type.";
+ reference
+ "RFC 2460: Internet Protocol, Version 6 (IPv6) Specification
+ Section 5";
+
+ }
+
+ list address {
+ key "ip";
+ description
+ "The list of configured IPv6 addresses on the interface.";
+ leaf ip {
+ type inet:ipv6-address-no-zone;
+ description
+ "The IPv6 address on the interface.";
+ }
+
+ leaf prefix-length {
+ type uint8 {
+ range "0..128";
+ }
+ mandatory true;
+ description
+ "The length of the subnet prefix.";
+ }
+ } // list address
+
+ list neighbor {
+ key "ip";
+ description
+ "A list of mappings from IPv6 addresses to
+ link-layer addresses.
+
+ Entries in this list are used as static entries in the
+ Neighbor Cache.";
+ reference
+ "RFC 4861: Neighbor Discovery for IP version 6 (IPv6)";
+
+ leaf ip {
+ type inet:ipv6-address-no-zone;
+ description
+ "The IPv6 address of the neighbor node.";
+ }
+
+ leaf link-layer-address {
+ type yang:phys-address;
+ mandatory true;
+ description
+ "The link-layer address of the neighbor node.";
+ }
+ } // list neighbor
+
+ leaf dup-addr-detect-transmits {
+ type uint32;
+ default '1';
+ description
+ "The number of consecutive Neighbor Solicitation messages
+ sent while performing Duplicate Address Detection on a
+ tentative address. A value of zero indicates that
+ Duplicate Address Detection is not performed on
+ tentative addresses. A value of one indicates a single
+ transmission with no follow-up retransmissions.";
+ reference
+ "RFC 4862: IPv6 Stateless Address Autoconfiguration";
+
+ }
+
+ container autoconf {
+ description
+ "Parameters to control the autoconfiguration of IPv6
+ addresses, as described in RFC 4862.";
+ reference
+ "RFC 4862: IPv6 Stateless Address Autoconfiguration";
+
+ leaf create-global-addresses {
+ type boolean;
+ default 'true';
+ description
+ "If enabled, the host creates global addresses as
+ described in RFC 4862.";
+ reference
+ "RFC 4862: IPv6 Stateless Address Autoconfiguration
+ Section 5.5";
+
+ }
+
+ leaf create-temporary-addresses {
+ if-feature ipv6-privacy-autoconf;
+ type boolean;
+ default 'false';
+ description
+ "If enabled, the host creates temporary addresses as
+ described in RFC 4941.";
+ reference
+ "RFC 4941: Privacy Extensions for Stateless Address
+ Autoconfiguration in IPv6";
+
+ }
+
+ leaf temporary-valid-lifetime {
+ if-feature ipv6-privacy-autoconf;
+ type uint32;
+ units "seconds";
+ default '604800';
+ description
+ "The time period during which the temporary address
+ is valid.";
+ reference
+ "RFC 4941: Privacy Extensions for Stateless Address
+ Autoconfiguration in IPv6
+ - TEMP_VALID_LIFETIME";
+
+ }
+
+ leaf temporary-preferred-lifetime {
+ if-feature ipv6-privacy-autoconf;
+ type uint32;
+ units "seconds";
+ default '86400';
+ description
+ "The time period during which the temporary address is
+ preferred.";
+ reference
+ "RFC 4941: Privacy Extensions for Stateless Address
+ Autoconfiguration in IPv6
+ - TEMP_PREFERRED_LIFETIME";
+
+ }
+ } // container autoconf
+ } // container ipv6
+ }
+
+ augment /if:interfaces-state/if:interface {
+ description
+ "Data nodes for the operational state of IP on interfaces.";
+ container ipv4 {
+ presence
+ "Present if IPv4 is enabled on this interface";
+ config false;
+ description
+ "Interface-specific parameters for the IPv4 address family.";
+ leaf forwarding {
+ type boolean;
+ description
+ "Indicates whether IPv4 packet forwarding is enabled or
+ disabled on this interface.";
+ }
+
+ leaf mtu {
+ type uint16 {
+ range "68..max";
+ }
+ units "octets";
+ description
+ "The size, in octets, of the largest IPv4 packet that the
+ interface will send and receive.";
+ reference
+ "RFC 791: Internet Protocol";
+
+ }
+
+ list address {
+ key "ip";
+ description
+ "The list of IPv4 addresses on the interface.";
+ leaf ip {
+ type inet:ipv4-address-no-zone;
+ description
+ "The IPv4 address on the interface.";
+ }
+
+ choice subnet {
+ description
+ "The subnet can be specified as a prefix-length, or,
+ if the server supports non-contiguous netmasks, as
+ a netmask.";
+ leaf prefix-length {
+ type uint8 {
+ range "0..32";
+ }
+ description
+ "The length of the subnet prefix.";
+ }
+ leaf netmask {
+ if-feature ipv4-non-contiguous-netmasks;
+ type yang:dotted-quad;
+ description
+ "The subnet specified as a netmask.";
+ }
+ } // choice subnet
+
+ leaf origin {
+ type ip-address-origin;
+ description
+ "The origin of this address.";
+ }
+ } // list address
+
+ list neighbor {
+ key "ip";
+ description
+ "A list of mappings from IPv4 addresses to
+ link-layer addresses.
+
+ This list represents the ARP Cache.";
+ reference
+ "RFC 826: An Ethernet Address Resolution Protocol";
+
+ leaf ip {
+ type inet:ipv4-address-no-zone;
+ description
+ "The IPv4 address of the neighbor node.";
+ }
+
+ leaf link-layer-address {
+ type yang:phys-address;
+ description
+ "The link-layer address of the neighbor node.";
+ }
+
+ leaf origin {
+ type neighbor-origin;
+ description
+ "The origin of this neighbor entry.";
+ }
+ } // list neighbor
+ } // container ipv4
+
+ container ipv6 {
+ presence
+ "Present if IPv6 is enabled on this interface";
+ config false;
+ description
+ "Parameters for the IPv6 address family.";
+ leaf forwarding {
+ type boolean;
+ default 'false';
+ description
+ "Indicates whether IPv6 packet forwarding is enabled or
+ disabled on this interface.";
+ reference
+ "RFC 4861: Neighbor Discovery for IP version 6 (IPv6)
+ Section 6.2.1, IsRouter";
+
+ }
+
+ leaf mtu {
+ type uint32 {
+ range "1280..max";
+ }
+ units "octets";
+ description
+ "The size, in octets, of the largest IPv6 packet that the
+ interface will send and receive.";
+ reference
+ "RFC 2460: Internet Protocol, Version 6 (IPv6) Specification
+ Section 5";
+
+ }
+
+ list address {
+ key "ip";
+ description
+ "The list of IPv6 addresses on the interface.";
+ leaf ip {
+ type inet:ipv6-address-no-zone;
+ description
+ "The IPv6 address on the interface.";
+ }
+
+ leaf prefix-length {
+ type uint8 {
+ range "0..128";
+ }
+ mandatory true;
+ description
+ "The length of the subnet prefix.";
+ }
+
+ leaf origin {
+ type ip-address-origin;
+ description
+ "The origin of this address.";
+ }
+
+ leaf status {
+ type enumeration {
+ enum "preferred" {
+ value 0;
+ description
+ "This is a valid address that can appear as the
+ destination or source address of a packet.";
+ }
+ enum "deprecated" {
+ value 1;
+ description
+ "This is a valid but deprecated address that should
+ no longer be used as a source address in new
+ communications, but packets addressed to such an
+ address are processed as expected.";
+ }
+ enum "invalid" {
+ value 2;
+ description
+ "This isn't a valid address, and it shouldn't appear
+ as the destination or source address of a packet.";
+ }
+ enum "inaccessible" {
+ value 3;
+ description
+ "The address is not accessible because the interface
+ to which this address is assigned is not
+ operational.";
+ }
+ enum "unknown" {
+ value 4;
+ description
+ "The status cannot be determined for some reason.";
+ }
+ enum "tentative" {
+ value 5;
+ description
+ "The uniqueness of the address on the link is being
+ verified. Addresses in this state should not be
+ used for general communication and should only be
+ used to determine the uniqueness of the address.";
+ }
+ enum "duplicate" {
+ value 6;
+ description
+ "The address has been determined to be non-unique on
+ the link and so must not be used.";
+ }
+ enum "optimistic" {
+ value 7;
+ description
+ "The address is available for use, subject to
+ restrictions, while its uniqueness on a link is
+ being verified.";
+ }
+ }
+ description
+ "The status of an address. Most of the states correspond
+ to states from the IPv6 Stateless Address
+ Autoconfiguration protocol.";
+ reference
+ "RFC 4293: Management Information Base for the
+ Internet Protocol (IP)
+ - IpAddressStatusTC
+ RFC 4862: IPv6 Stateless Address Autoconfiguration";
+
+ }
+ } // list address
+
+ list neighbor {
+ key "ip";
+ description
+ "A list of mappings from IPv6 addresses to
+ link-layer addresses.
+
+ This list represents the Neighbor Cache.";
+ reference
+ "RFC 4861: Neighbor Discovery for IP version 6 (IPv6)";
+
+ leaf ip {
+ type inet:ipv6-address-no-zone;
+ description
+ "The IPv6 address of the neighbor node.";
+ }
+
+ leaf link-layer-address {
+ type yang:phys-address;
+ description
+ "The link-layer address of the neighbor node.";
+ }
+
+ leaf origin {
+ type neighbor-origin;
+ description
+ "The origin of this neighbor entry.";
+ }
+
+ leaf is-router {
+ type empty;
+ description
+ "Indicates that the neighbor node acts as a router.";
+ }
+
+ leaf state {
+ type enumeration {
+ enum "incomplete" {
+ value 0;
+ description
+ "Address resolution is in progress, and the link-layer
+ address of the neighbor has not yet been
+ determined.";
+ }
+ enum "reachable" {
+ value 1;
+ description
+ "Roughly speaking, the neighbor is known to have been
+ reachable recently (within tens of seconds ago).";
+ }
+ enum "stale" {
+ value 2;
+ description
+ "The neighbor is no longer known to be reachable, but
+ until traffic is sent to the neighbor no attempt
+ should be made to verify its reachability.";
+ }
+ enum "delay" {
+ value 3;
+ description
+ "The neighbor is no longer known to be reachable, and
+ traffic has recently been sent to the neighbor.
+ Rather than probe the neighbor immediately, however,
+ delay sending probes for a short while in order to
+ give upper-layer protocols a chance to provide
+ reachability confirmation.";
+ }
+ enum "probe" {
+ value 4;
+ description
+ "The neighbor is no longer known to be reachable, and
+ unicast Neighbor Solicitation probes are being sent
+ to verify reachability.";
+ }
+ }
+ description
+ "The Neighbor Unreachability Detection state of this
+ entry.";
+ reference
+ "RFC 4861: Neighbor Discovery for IP version 6 (IPv6)
+ Section 7.3.2";
+
+ }
+ } // list neighbor
+ } // container ipv6
+ }
+} // module ietf-ip
--- /dev/null
+module v3po {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:v3po";
+ prefix "v3po";
+
+ revision "2015-01-05" {
+ description "Initial revision of v3po model";
+ }
+
+ import iana-if-type {
+ prefix "ianaift";
+ }
+ import ietf-interfaces {
+ prefix "if";
+ }
+ import ietf-yang-types {
+ prefix "yang";
+ }
+ import ietf-inet-types {
+ prefix "inet";
+ }
+ import ietf-ip {
+ prefix "ip";
+ }
+ import yang-ext {
+ prefix "ext";
+ }
+
+ typedef bridge-domain-ref {
+ type leafref {
+ path "/vpp/bridge-domains/bridge-domain/name";
+ }
+ description
+ "This type is used by to reference a bridge domain table";
+ }
+
+ typedef bridged-virtual-interface-ref {
+ type leafref {
+ path "/if:interfaces/if:interface/l2/bridged-virtual-interface";
+ }
+ description
+ "This type is used by to reference a bridged virtual interface";
+ }
+
+ typedef vlan-type {
+ type enumeration {
+ enum 802dot1q;
+ enum 802dot1ad;
+ }
+ }
+
+ typedef tag-rewrite-operation {
+ type enumeration {
+ enum disabled;
+ enum push-1;
+ enum push-2;
+ enum pop-1;
+ enum pop-2;
+ enum translate-1-to-1;
+ enum translate-1-to-2;
+ enum translate-2-to-1;
+ enum translate-2-to-2;
+ }
+ }
+
+ typedef vlan-tag {
+ type uint16 {
+ range "1..4094";
+ }
+ }
+
+ identity vxlan-tunnel {
+ base if:interface-type;
+ }
+
+ identity vhost-user {
+ base if:interface-type;
+ }
+
+ identity tap {
+ base if:interface-type;
+ }
+
+ identity sub-interface {
+ base if:interface-type;
+ }
+
+ typedef vxlan-vni {
+ // FIXME: should be in a vxlan-specific model
+ description "VNI used in a VXLAN tunnel";
+ type uint32 {
+ range "0..16777215";
+ }
+ }
+
+ typedef vhost-user-role {
+ type enumeration {
+ enum "server";
+ enum "client";
+ }
+ }
+
+ grouping bridge-domain-attributes {
+ leaf flood {
+ type boolean;
+ default true;
+ description
+ "Enable/disable L2 flooding.";
+ }
+ leaf forward {
+ type boolean;
+ default true;
+ description
+ "Enable/disable L2 forwarding.";
+ }
+ leaf learn {
+ type boolean;
+ default true;
+ description
+ "Enable/disable L2 learning.";
+ }
+ leaf unknown-unicast-flood {
+ type boolean;
+ default true;
+ }
+ leaf arp-termination {
+ type boolean;
+ default false;
+ }
+ }
+
+ grouping sub-interface-base-attributes {
+ leaf identifier {
+ type uint32;
+ }
+ leaf vlan-type {
+ type vlan-type;
+ default '802dot1q';
+ }
+ leaf number-of-tags {
+ type uint8 {
+ range "0..2";
+ }
+ default 1;
+ }
+ leaf outer-id {
+ type vlan-tag;
+ }
+ leaf inner-id {
+ type vlan-tag;
+ }
+ leaf match-any-outer-id {
+ type empty;
+ }
+ leaf match-any-inner-id {
+ type empty;
+ }
+ leaf exact-match {
+ type empty;
+ }
+ leaf default-subif {
+ type empty;
+ }
+ }
+
+ grouping tap-interface-base-attributes {
+ leaf tap-name {
+ type string;
+ }
+ }
+
+ grouping tap-interface-config-attributes {
+ leaf mac {
+ type yang:phys-address;
+ mandatory false;
+ description "Mac address to be set for the tap interface. Random will be used if not configured";
+ }
+
+ leaf device-instance {
+ type uint32;
+ mandatory false;
+ description "Custom device instance. Autogenerated will be used if not configured";
+ }
+ }
+
+ grouping vhost-user-interface-base-attributes {
+ leaf socket {
+ type string {
+ length 1..255;
+ }
+ }
+ leaf role {
+ type vhost-user-role;
+ default "server";
+ }
+ }
+
+ grouping vhost-user-interface-state-attributes {
+ leaf features {
+ type uint64;
+ config false;
+ }
+ leaf virtio-net-hdr-size {
+ type uint32;
+ config false;
+ }
+ leaf num-memory-regions {
+ type uint32;
+ config false;
+ }
+ leaf connect-error {
+ type string;
+ config false;
+ }
+ }
+
+ grouping vlan-tag-rewrite-attributes {
+ leaf rewrite-operation {
+ type tag-rewrite-operation;
+ default 'disabled';
+ }
+ leaf first-pushed {
+ type vlan-type;
+ default '802dot1q';
+ }
+ leaf tag1 {
+ type vlan-tag;
+ }
+ leaf tag2 {
+ type vlan-tag;
+ }
+ }
+
+ augment /if:interfaces/if:interface {
+ ext:augment-identifier "vpp-interface-augmentation";
+
+ // FIXME using ietf-interfaces model for vpp interfaces makes it hard to implement because:
+ // 1. The link between interface type and this augmentation is unclear
+ // 2. Only this augmentation with combination of ifc type is trigger to do something for vpp, what if user only configures base interface stuff ? + We need to get leaves defined by ietf-interfaces when we are processing this augment
+
+ container sub-interface {
+ when "../if:type = 'v3po:sub-interface'";
+ leaf super-interface {
+ type if:interface-ref;
+ }
+ uses sub-interface-base-attributes;
+ }
+
+ container tap {
+ when "../if:type = 'v3po:tap'";
+ uses tap-interface-base-attributes;
+ uses tap-interface-config-attributes;
+ }
+
+ container ethernet {
+ when "../if:type = 'ianaift:ethernetCsmacd'";
+ leaf mtu {
+ type uint16 {
+ range "64..9216";
+ }
+ units "octets";
+ default 9216;
+ description
+ "The size, in octets, of the largest packet that the
+ hardware interface will send and receive.";
+ }
+ }
+ container routing {
+ leaf vrf-id {
+ type uint32;
+ default 0;
+ }
+ }
+ container vhost-user {
+ when "../if:type = 'v3po:vhost-user'";
+ uses vhost-user-interface-base-attributes;
+ description "vhost-user settings";
+ }
+ container vxlan {
+ // FIXME: this should be in an vxlan-specific extension
+ when "../if:type = 'v3po:vxlan-tunnel'";
+
+ leaf src {
+ /*mandatory true;*/
+ type inet:ip-address;
+ }
+ leaf dst {
+ /*mandatory true;*/
+ type inet:ip-address;
+ }
+ leaf vni {
+ /*mandatory true;*/
+ type vxlan-vni;
+ }
+ leaf encap-vrf-id {
+ type uint32;
+ }
+ }
+ container l2 {
+ description
+ "Parameters for configuring Layer2 features on interfaces.";
+ must "(not (../if:ipv4[if:enabled = 'true']/if:address/if:ip) and " +
+ "not (../if:ipv6[if:enabled = 'true']/if:address/if:ip))";
+
+ choice interconnection {
+ case xconnect-based {
+ leaf xconnect-outgoing-interface {
+ /* Don't allow selection of this interface */
+ must "../../if:name != current()";
+ type if:interface-ref;
+ description
+ "L2 xconnect mode";
+ }
+ }
+ case bridge-based {
+ leaf bridge-domain {
+ type bridge-domain-ref;
+ description
+ "Interfaces in a bridge-domain forward packets to other
+ interfaces in the same bridge-domain based on
+ destination mac address.";
+ }
+ leaf split-horizon-group {
+ when "../bridge-domain";
+ type uint8 {
+ range "0..255";
+ }
+ default 0;
+ description
+ "Interface's split-horizon group. Interfaces in the same
+ bridge-domain and split-horizon group can not forward
+ packets between each other. ";
+ }
+ leaf bridged-virtual-interface {
+ when "../bridge-domain";
+ type boolean;
+ default false;
+ description
+ "Interface forward packets in the bridge-domain
+ associated with the BVI.";
+ }
+ }
+ }
+ container vlan-tag-rewrite {
+ uses vlan-tag-rewrite-attributes;
+ }
+ }
+ }
+
+ container vpp {
+ description
+ "VPP config data";
+
+ container bridge-domains {
+ list bridge-domain {
+ key "name";
+ // TODO: where does this come from?
+ max-elements 1024;
+
+ leaf name {
+ type string;
+ }
+
+ uses bridge-domain-attributes;
+
+ list l2-fib {
+ key "phys-address";
+
+ leaf phys-address {
+ type yang:phys-address;
+ }
+ leaf action {
+ type enumeration {
+ enum "forward";
+ enum "filter";
+ }
+ mandatory true;
+ }
+ leaf outgoing-interface {
+ type if:interface-ref;
+ }
+ }
+ }
+ }
+ }
+
+ augment /if:interfaces-state/if:interface {
+ ext:augment-identifier "vpp-interface-state-augmentation";
+
+ leaf description {
+ type string;
+ }
+
+ container sub-interface {
+ when "../if:type = 'v3po:sub-interface'";
+ leaf super-interface {
+ type if:interface-state-ref;
+ }
+ uses sub-interface-base-attributes;
+ }
+
+ container tap {
+ when "../if:type = 'v3po:tap'";
+ uses tap-interface-base-attributes {
+ refine tap-name {
+ config false;
+ }
+ }
+ }
+
+ container ethernet {
+ when "../if:type = 'ianaift:ethernetCsmacd'";
+ leaf mtu {
+ type uint16;
+ }
+ leaf manufacturer-description {
+ type string;
+ }
+ leaf duplex {
+ type enumeration {
+ enum "half";
+ enum "full";
+ }
+ }
+ }
+ container vhost-user {
+ when "../if:type = 'v3po:vhost-user'";
+ uses vhost-user-interface-base-attributes {
+ refine socket {
+ config false;
+ }
+ refine role {
+ config false;
+ }
+ }
+ uses vhost-user-interface-state-attributes;
+ }
+ container vxlan {
+ when "../if:type = 'v3po:vxlan-tunnel'";
+
+ leaf src {
+ type inet:ip-address;
+ }
+ leaf dst {
+ type inet:ip-address;
+ }
+
+ leaf vni {
+ type uint32;
+ }
+ leaf encap-vrf-id {
+ type uint32;
+ }
+ }
+ container l2 {
+ choice interconnection {
+ case xconnect-based {
+ leaf xconnect-outgoing-interface {
+ type if:interface-ref;
+ }
+ }
+ case bridge-based {
+ leaf bridge-domain {
+ type bridge-domain-ref;
+ }
+ leaf split-horizon-group {
+ type uint8;
+ }
+ leaf bridged-virtual-interface {
+ type boolean;
+ }
+ }
+ }
+ container vlan-tag-rewrite {
+ uses vlan-tag-rewrite-attributes;
+ }
+ }
+ }
+
+ augment /if:interfaces-state/if:interface/if:statistics {
+ ext:augment-identifier "vpp-interface-statistics-augmentation";
+ leaf in-errors-no-buf {
+ type yang:counter64;
+ }
+ leaf in-errors-miss {
+ type yang:counter64;
+ }
+ leaf out-discards-fifo-full {
+ type yang:counter64;
+ }
+ }
+
+ container vpp-state {
+ config false;
+
+ description
+ "VPP operational data";
+
+ container bridge-domains {
+ // FIXME: Should this live in bridge-domain.yang in a modular fashion ?
+ list bridge-domain {
+
+ key "name";
+ leaf name {
+ type string;
+ }
+
+ uses bridge-domain-attributes;
+
+ list interface {
+ key "name";
+
+ leaf name {
+ type if:interface-state-ref;
+ }
+
+ leaf split-horizon-group {
+ type uint8;
+ }
+
+ leaf bridged-virtual-interface {
+ type boolean;
+ }
+ }
+
+ list l2-fib {
+ key "phys-address";
+
+ leaf phys-address {
+ type yang:phys-address;
+ }
+ leaf static-config {
+ type boolean;
+ }
+ leaf outgoing-interface {
+ when "../v3po:action = 'forward'";
+ type if:interface-state-ref;
+ }
+ leaf action {
+ type enumeration {
+ enum "forward";
+ enum "filter";
+ }
+ mandatory true;
+ }
+ leaf bridged-virtual-interface {
+ when "../v3po:action = 'forward'";
+ type boolean;
+ }
+ }
+ description
+ "bridge-domain operational data";
+ }
+ }
+
+ container version {
+ leaf name {
+ type string;
+ }
+ leaf build-directory {
+ type string;
+ }
+ leaf build-date {
+ type string;
+ }
+ leaf branch {
+ type string;
+ }
+ description
+ "vlib version info";
+ }
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 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,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.vpp;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import java.io.IOException;
+import java.util.Collection;
+
+import javax.annotation.Nonnull;
+
+import org.opendaylight.controller.md.sal.binding.test.AbstractDataBrokerTest;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSet.Builder;
+
+/**
+ * Loads only modules of GBP and it's dependencies for data broker.
+ * <br>
+ * Therefore this implementation is faster than {@link AbstractDataBrokerTest}
+ */
+public abstract class CustomDataBrokerTest extends AbstractDataBrokerTest {
+
+ public static void loadModuleInfos(Class<?> clazzFromModule, Builder<YangModuleInfo> moduleInfoSet)
+ throws Exception {
+ YangModuleInfo moduleInfo = BindingReflections.getModuleInfo(clazzFromModule);
+ checkState(moduleInfo != null, "Module Info for %s is not available.", clazzFromModule);
+ collectYangModuleInfo(moduleInfo, moduleInfoSet);
+ }
+
+ private static void collectYangModuleInfo(final YangModuleInfo moduleInfo,
+ final Builder<YangModuleInfo> moduleInfoSet) throws IOException {
+ moduleInfoSet.add(moduleInfo);
+ for (YangModuleInfo dependency : moduleInfo.getImportedModules()) {
+ collectYangModuleInfo(dependency, moduleInfoSet);
+ }
+ }
+
+ @Override
+ protected Iterable<YangModuleInfo> getModuleInfos() throws Exception {
+ Builder<YangModuleInfo> moduleInfoSet = ImmutableSet.<YangModuleInfo>builder();
+ for (Class<?> clazz : getClassesFromModules()) {
+ loadModuleInfos(clazz, moduleInfoSet);
+ }
+ return moduleInfoSet.build();
+ }
+
+ /**
+ * @return a class from every yang module which needs to be loaded. Cannot return {@code null}
+ * or empty collection.
+ */
+ public abstract @Nonnull Collection<Class<?>> getClassesFromModules();
+}
--- /dev/null
+/*\r
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+\r
+package org.opendaylight.groupbasedpolicy.renderer.vpp;\r
+\r
+import com.google.common.collect.ImmutableList;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.VhostUser;\r
+\r
+import javax.annotation.Nonnull;\r
+import java.util.Collection;\r
+\r
+public class VppRendererDataBrokerTest extends CustomDataBrokerTest {\r
+\r
+ @Nonnull\r
+ @Override\r
+ public Collection<Class<?>> getClassesFromModules() {\r
+ return ImmutableList.of(Interfaces.class, Interface.class, VhostUser.class);\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (c) 2016 Cisco Systems. All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+\r
+package org.opendaylight.groupbasedpolicy.renderer.vpp.commands;\r
+\r
+import com.google.common.base.Optional;\r
+import org.junit.Assert;\r
+import org.junit.Before;\r
+import org.junit.Test;\r
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;\r
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;\r
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;\r
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;\r
+import org.opendaylight.groupbasedpolicy.renderer.vpp.VppRendererDataBrokerTest;\r
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General;\r
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;\r
+import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VhostUserRole;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentation;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VppInterfaceAugmentationBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.L2Builder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.VhostUser;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.VhostUserBuilder;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.l2.interconnection.BridgeBased;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.interfaces._interface.l2.interconnection.BridgeBasedBuilder;\r
+\r
+public class VhostUserCommandTest extends VppRendererDataBrokerTest {\r
+\r
+ private final static String BRIDGE_DOMAIN = "testBD";\r
+ private final static String DESCRIPTION = "used for testing";\r
+ private final static String INTERFACE_NAME = "testInterface";\r
+ private final static String SOCKET_NAME = "soc1";\r
+\r
+ private final static String UPD_BRIDGE_DOMAIN = "testBD2";\r
+ private final static String UPD_DESCRIPTION = "updated description";\r
+ private final static String UPD_SOCKET_NAME = "soc2";\r
+ private final static short SPLIT_HORIZON_GROUP_DEFAULT = 0;\r
+ private final static boolean IS_BRIDGED_DEFAULT = false;\r
+\r
+ private static Interface BASIC_INTERFACE;\r
+\r
+ private DataBroker dataBroker;\r
+\r
+ @Before\r
+ public void init() {\r
+ dataBroker = getDataBroker();\r
+\r
+ VhostUser vhostUser = new VhostUserBuilder().setRole(VhostUserRole.Server).setSocket(SOCKET_NAME).build();\r
+\r
+ VppInterfaceAugmentation vppAugmentation = new VppInterfaceAugmentationBuilder().setVhostUser(vhostUser)\r
+ .setL2(new L2Builder().setInterconnection(new BridgeBasedBuilder().setBridgeDomain(BRIDGE_DOMAIN)\r
+ .setSplitHorizonGroup(SPLIT_HORIZON_GROUP_DEFAULT)\r
+ .setBridgedVirtualInterface(IS_BRIDGED_DEFAULT)\r
+ .build()).build())\r
+ .build();\r
+\r
+ BASIC_INTERFACE =\r
+ new InterfaceBuilder().setDescription(DESCRIPTION)\r
+ .setEnabled(true)\r
+ .setKey(new InterfaceKey(INTERFACE_NAME))\r
+ .setName(INTERFACE_NAME)\r
+ .setType(\r
+ org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev150105.VhostUser.class)\r
+ .setLinkUpDownTrapEnable(Interface.LinkUpDownTrapEnable.Enabled)\r
+ .addAugmentation(VppInterfaceAugmentation.class, vppAugmentation)\r
+ .build();\r
+ }\r
+\r
+ @Test\r
+ public void AddVhostTest() {\r
+ ReadWriteTransaction transaction = dataBroker.newReadWriteTransaction();\r
+ VhostUserCommand addCommand = VhostUserCommand.builder()\r
+ .setOperation(General.Operations.PUT)\r
+ .setName(INTERFACE_NAME)\r
+ .setDescription(DESCRIPTION)\r
+ .setRole(VhostUserRole.Server)\r
+ .setSocket(SOCKET_NAME)\r
+ .setBridgeDomain(BRIDGE_DOMAIN)\r
+ .setEnabled(true)\r
+ .build();\r
+\r
+ addCommand.execute(transaction);\r
+\r
+ transaction.submit();\r
+\r
+ ReadOnlyTransaction readOnlyTransaction = dataBroker.newReadOnlyTransaction();\r
+\r
+ Optional<Interface> optional = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,\r
+ VppIidFactory.getInterfaceIID(new InterfaceKey(INTERFACE_NAME)), readOnlyTransaction);\r
+\r
+ Assert.assertTrue("Interface was not written to DS", optional.isPresent());\r
+\r
+ Interface anInterface = optional.get();\r
+\r
+ Assert.assertEquals(BASIC_INTERFACE, anInterface);\r
+\r
+ }\r
+\r
+ @Test\r
+ public void DeleteVhostTest() {\r
+ ReadWriteTransaction transaction = dataBroker.newReadWriteTransaction();\r
+\r
+ transaction.put(LogicalDatastoreType.CONFIGURATION, VppIidFactory.getInterfaceIID(BASIC_INTERFACE.getKey()),\r
+ BASIC_INTERFACE, true);\r
+ transaction.submit();\r
+\r
+ Optional<Interface> optional = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,\r
+ VppIidFactory.getInterfaceIID(BASIC_INTERFACE.getKey()), dataBroker.newReadOnlyTransaction());\r
+\r
+ Assert.assertTrue("Interface was not written to DS", optional.isPresent());\r
+\r
+ VhostUserCommand deleteCommand = VhostUserCommand.builder()\r
+ .setOperation(General.Operations.DELETE)\r
+ .setName(INTERFACE_NAME)\r
+ .setSocket(SOCKET_NAME)\r
+ .build();\r
+\r
+ ReadWriteTransaction deleteTransaction = dataBroker.newReadWriteTransaction();\r
+ deleteCommand.execute(deleteTransaction);\r
+ deleteTransaction.submit();\r
+\r
+ Optional<Interface> optionalDeleted = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,\r
+ VppIidFactory.getInterfaceIID(new InterfaceKey(deleteCommand.getName())),\r
+ dataBroker.newReadOnlyTransaction());\r
+\r
+ Assert.assertFalse("Interface was not deleted from DS", optionalDeleted.isPresent());\r
+ }\r
+\r
+ @Test\r
+ public void UpdateVhostTest() {\r
+ ReadWriteTransaction transaction = dataBroker.newReadWriteTransaction();\r
+\r
+ transaction.put(LogicalDatastoreType.CONFIGURATION, VppIidFactory.getInterfaceIID(BASIC_INTERFACE.getKey()),\r
+ BASIC_INTERFACE, true);\r
+ transaction.submit();\r
+\r
+ Optional<Interface> optional = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,\r
+ VppIidFactory.getInterfaceIID(BASIC_INTERFACE.getKey()), dataBroker.newReadOnlyTransaction());\r
+\r
+ Assert.assertTrue("Interface was not written to DS", optional.isPresent());\r
+\r
+ VhostUserCommand updateCommand = VhostUserCommand.builder()\r
+ .setOperation(General.Operations.MERGE)\r
+ .setName(INTERFACE_NAME)\r
+ .setDescription(UPD_DESCRIPTION)\r
+ .setEnabled(false)\r
+ .setRole(VhostUserRole.Client)\r
+ .setSocket(UPD_SOCKET_NAME)\r
+ .setBridgeDomain(UPD_BRIDGE_DOMAIN)\r
+ .build();\r
+\r
+ ReadWriteTransaction deleteTransaction = dataBroker.newReadWriteTransaction();\r
+ updateCommand.execute(deleteTransaction);\r
+ deleteTransaction.submit();\r
+\r
+ Optional<Interface> optionalUpdated = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,\r
+ VppIidFactory.getInterfaceIID(new InterfaceKey(updateCommand.getName())),\r
+ dataBroker.newReadOnlyTransaction());\r
+\r
+ Assert.assertTrue("Interface was not found in DS", optionalUpdated.isPresent());\r
+ Interface updatedInterface = optionalUpdated.get();\r
+\r
+ Assert.assertEquals(UPD_DESCRIPTION, updatedInterface.getDescription());\r
+ Assert.assertFalse(updatedInterface.isEnabled());\r
+ VppInterfaceAugmentation vppInterfaceAugmentation =\r
+ updatedInterface.getAugmentation(VppInterfaceAugmentation.class);\r
+ Assert.assertEquals(VhostUserRole.Client, vppInterfaceAugmentation.getVhostUser().getRole());\r
+ Assert.assertEquals(UPD_SOCKET_NAME, vppInterfaceAugmentation.getVhostUser().getSocket());\r
+\r
+ Assert.assertTrue(vppInterfaceAugmentation.getL2().getInterconnection() instanceof BridgeBased);\r
+\r
+ Assert.assertEquals(UPD_BRIDGE_DOMAIN,\r
+ ((BridgeBased) vppInterfaceAugmentation.getL2().getInterconnection()).getBridgeDomain());\r
+ }\r
+}\r