infix-vlan: Create a custom vlan model

This implements the new model infix-if-vlan.
The new CLI is:

root@infix-00-00-00:/config/interfaces/interface/vlan10/> set vlan id 10 lower-layer-if eth0

with an possible extra option for tag-type, default tag-type is c-vlan.
This commit is contained in:
Mattias Walström
2023-10-27 10:53:55 +02:00
committed by Joachim Wiberg
parent be8bad9885
commit 941fc31581
9 changed files with 117 additions and 615 deletions
+8 -5
View File
@@ -56,8 +56,6 @@ class Iface:
self.in_octets = ''
self.out_octets = ''
self.parent = data.get('ietf-if-extensions:parent-interface', None)
if self.data.get('ietf-ip:ipv4'):
self.mtu = self.data.get('ietf-ip:ipv4').get('mtu', '')
self.ipv4_addr = self.data.get('ietf-ip:ipv4').get('address', '')
@@ -75,6 +73,11 @@ class Iface:
else:
self.bridge = ''
if self.data.get('infix-interfaces:vlan'):
self.lower_if = self.data.get('infix-interfaces:vlan', None).get('lower-layer-if',None)
else:
self.lower_if = ''
def is_vlan(self):
return self.data['type'] == "infix-if-type:vlan"
@@ -136,7 +139,7 @@ class Iface:
self.pr_name(pipe="")
self.pr_proto_eth()
if self.parent:
if self.lower_if:
self.pr_proto_ipv4(pipe='│')
self.pr_proto_ipv6(pipe='│')
else:
@@ -144,7 +147,7 @@ class Iface:
self.pr_proto_ipv6()
return
parent = find_iface(_ifaces, self.parent)
parent = find_iface(_ifaces, self.lower_if)
if not parent:
print(f"Error, didn't find parent interface for vlan {self.name}")
sys.exit(1)
@@ -227,7 +230,7 @@ def pr_interface_list(json):
continue
# These interfaces are printed by there parent, such as bridge
if iface.parent:
if iface.lower_if:
continue
if iface.bridge:
continue
-4
View File
@@ -147,11 +147,7 @@ sysrepoctl -s $SEARCH \
-i ietf-yang-push@2019-09-09.yang -g wheel -p 0660 \
-e on-change \
-i iana-if-type@2023-01-26.yang -g wheel -p 0660 \
-i ietf-if-extensions@2023-01-26.yang -g wheel -p 0660 \
-e sub-interfaces \
-i ieee802-dot1q-types@2022-10-29.yang -g wheel -p 0660 \
-i ietf-if-vlan-encapsulation@2023-01-26.yang \
-g wheel -p 0660 \
-i infix-ip@2023-09-14.yang -g wheel -p 0660 \
-i infix-if-type@2023-08-21.yang -g wheel -p 0660 \
-i infix-interfaces@2023-09-19.yang -g wheel -p 0660 \
+33 -50
View File
@@ -168,43 +168,37 @@ static int ifchange_cand_infer_vlan(sr_session_ctx_t *session, const char *path)
goto out_free_ifname;
err = srx_nitems(session, &cnt,
"%s/ietf-if-extensions:parent-interface", xpath);
"%s/infix-if-vlan:vlan"
"/lower-layer-if", xpath);
if (!err && !cnt) {
inferred.data.string_val = ifname;
err = srx_set_item(session, &inferred, 0,
"%s/ietf-if-extensions:parent-interface", xpath);
"%s/infix-if-vlan:vlan"
"/lower-layer-if", xpath);
if (err)
goto out_free_ifname;
}
err = srx_nitems(session, &cnt,
"%s"
"/ietf-if-extensions:encapsulation"
"/ietf-if-vlan-encapsulation:dot1q-vlan"
"/outer-tag/tag-type", xpath);
"%s/infix-if-vlan:vlan"
"/tag-type", xpath);
if (!err && !cnt) {
inferred.data.string_val = "ieee802-dot1q-types:c-vlan";
err = srx_set_item(session, &inferred, 0,
"%s"
"/ietf-if-extensions:encapsulation"
"/ietf-if-vlan-encapsulation:dot1q-vlan"
"/outer-tag/tag-type", xpath);
"%s/infix-if-vlan:vlan"
"/tag-type", xpath);
if (err)
goto out_free_ifname;
}
err = srx_nitems(session, &cnt,
"%s"
"/ietf-if-extensions:encapsulation"
"/ietf-if-vlan-encapsulation:dot1q-vlan"
"/outer-tag/vlan-id", xpath);
"%s/infix-if-vlan:vlan"
"/id", xpath);
if (!err && !cnt) {
inferred.data.string_val = vidstr;
err = srx_set_item(session, &inferred, 0,
"%s"
"/ietf-if-extensions:encapsulation"
"/ietf-if-vlan-encapsulation:dot1q-vlan"
"/outer-tag/vlan-id", xpath);
"%s/infix-if-vlan:vlan"
"/id", xpath);
if (err)
goto out_free_ifname;
}
@@ -891,38 +885,36 @@ static int netdag_gen_veth(struct dagger *net, struct lyd_node *dif,
static int netdag_gen_vlan(struct dagger *net, struct lyd_node *dif,
struct lyd_node *cif, FILE *ip)
{
const char *parent = lydx_get_cattr(cif, "parent-interface");
const char *ifname = lydx_get_cattr(cif, "name");
struct lydx_diff typed, vidd;
struct lyd_node *otag;
struct lyd_node *vlan;
const char *lower_if;
const char *proto;
int err;
DEBUG("ifname %s parent %s", ifname, parent);
err = dagger_add_dep(net, ifname, parent);
if (err)
return ERR_IFACE(cif, err, "Unable to add dep \"%s\"", parent);
otag = lydx_get_descendant(lyd_child(dif ? : cif),
"encapsulation",
"dot1q-vlan",
"outer-tag",
NULL);
if (!otag) {
vlan = lydx_get_descendant(lyd_child(dif ? : cif), "vlan", NULL);
if (!vlan) {
/*
* Note: this is only an error if outer-tag is missing
* Note: this is only an error if vlan subcontext is missing
* from cif, otherwise it just means the interface had a
* a change that was not related to the VLAN config.
*/
if (!dif)
ERROR("%s: missing mandatory outer-tag", ifname);
ERROR("%s: missing mandatory vlan", ifname);
return 0;
}
lower_if = lydx_get_cattr(vlan, "lower-layer-if");
DEBUG("ifname %s lower if %s\n", ifname, lower_if);
fprintf(ip, "link add dev %s down link %s type vlan", ifname, parent);
err = dagger_add_dep(net, ifname, lower_if);
if (err)
return ERR_IFACE(cif, err, "Unable to add dep \"%s\"", lower_if);
if (lydx_get_diff(lydx_get_child(otag, "tag-type"), &typed)) {
fprintf(ip, "link add dev %s down link %s type vlan", ifname, lower_if);
if (lydx_get_diff(lydx_get_child(vlan, "tag-type"), &typed)) {
proto = bridge_tagtype2str(typed.new);
if (!proto)
return ERR_IFACE(cif, -ENOSYS, "Unsupported tag type \"%s\"", typed.new);
@@ -930,7 +922,7 @@ static int netdag_gen_vlan(struct dagger *net, struct lyd_node *dif,
fprintf(ip, " proto %s", proto);
}
if (lydx_get_diff(lydx_get_child(otag, "vlan-id"), &vidd))
if (lydx_get_diff(lydx_get_child(vlan, "id"), &vidd))
fprintf(ip, " id %s", vidd.new);
fputc('\n', ip);
@@ -996,24 +988,15 @@ static bool netdag_must_del(struct lyd_node *dif, struct lyd_node *cif)
{
const char *iftype = lydx_get_cattr(cif, "type");
if (!strcmp(iftype, "infix-if-type:bridge")) {
if (is_phys_addr_deleted(dif))
return true;
} else if (!strcmp(iftype, "infix-if-type:vlan")) {
if (strcmp(iftype, "infix-if-type:ethernet")) {
if (is_phys_addr_deleted(dif))
return true;
}
if (lydx_get_cattr(dif, "parent-interface") ||
lydx_get_descendant(lyd_child(dif),
"encapsulation",
"dot1q-vlan",
"outer-tag",
NULL))
if (!strcmp(iftype, "infix-if-type:vlan")) {
if (lydx_get_descendant(lyd_child(dif), "vlan", NULL))
return true;
} else if (!strcmp(iftype, "infix-if-type:veth")) {
if (is_phys_addr_deleted(dif))
return true;
if (lydx_get_descendant(lyd_child(dif), "peer", NULL))
return true;
/*
@@ -1,535 +0,0 @@
module ietf-if-extensions {
yang-version 1.1;
namespace "urn:ietf:params:xml:ns:yang:ietf-if-extensions";
prefix if-ext;
import ietf-yang-types {
prefix yang;
reference "RFC 6991: Common YANG Data Types";
}
import ietf-interfaces {
prefix if;
reference
"RFC 8343: A YANG Data Model For Interface Management";
}
import iana-if-type {
prefix ianaift;
reference "RFC 7224: IANA Interface Type YANG Module";
}
organization
"IETF NETMOD (NETCONF Data Modeling Language) Working Group";
contact
"WG Web: <http://tools.ietf.org/wg/netmod/>
WG List: <mailto:netmod@ietf.org>
Editor: Robert Wilton
<mailto:rwilton@cisco.com>";
description
"This module contains common definitions for extending the IETF
interface YANG model (RFC 8343) with common configurable layer 2
properties.
Copyright (c) 2023 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 Revised BSD License set
forth in Section 4.c of the IETF Trust's Legal Provisions
Relating to IETF Documents
(https://trustee.ietf.org/license-info).
This version of this YANG module is part of RFC XXXX
(https://www.rfc-editor.org/info/rfcXXXX); see the RFC itself
for full legal notices.
The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', 'SHALL
NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', 'NOT RECOMMENDED',
'MAY', and 'OPTIONAL' in this document are to be interpreted as
described in BCP 14 (RFC 2119) (RFC 8174) when, and only when,
they appear in all capitals, as shown here.";
revision 2023-01-26 {
description
"Initial revision.";
reference
"RFC XXXX, Common Interface Extension YANG Data Models";
}
feature link-flap-suppression {
description
"This feature indicates that configurable interface link
delay is supported, which is a feature is used to limit the
propagation of very short interface link state flaps.";
reference "RFC XXXX, Section 2.1 Link Flap Suppression";
}
feature dampening {
description
"This feature indicates that the device supports interface
dampening, which is a feature that is used to limit the
propagation of interface link state flaps over longer
periods.";
reference "RFC XXXX, Section 2.2 Dampening";
}
feature loopback {
description
"This feature indicates that configurable interface loopback is
supported.";
reference "RFC XXXX, Section 2.4 Loopback";
}
feature max-frame-size {
description
"This feature indicates that the device supports configuring or
reporting the maximum frame size on interfaces.";
reference "RFC XXXX, Section 2.5 Maximum Frame Size";
}
feature sub-interfaces {
description
"This feature indicates that the device supports the
instantiation of sub-interfaces. Sub-interfaces are defined
as logical child interfaces that allow features and forwarding
decisions to be applied to a subset of the traffic processed
on the specified parent interface.";
reference "RFC XXXX, Section 2.6 Sub-interface";
}
/*
* Define common identities to help allow interface types to be
* assigned properties.
*/
identity sub-interface {
description
"Base type for generic sub-interfaces.
New or custom interface types can derive from this type to
inherit generic sub-interface configuration.";
reference "RFC XXXX, Section 2.6 Sub-interface";
}
identity ethSubInterface{
base ianaift:l2vlan;
base sub-interface;
description
"This identity represents the child sub-interface of any
interface types that uses Ethernet framing (with or without
802.1Q tagging).";
}
identity loopback {
description "Base identity for interface loopback options";
reference "RFC XXXX, Section 2.4";
}
identity internal {
base loopback;
description
"All egress traffic on the interface is internally looped back
within the interface to be received on the ingress path.";
reference "RFC XXXX, Section 2.4";
}
identity line {
base loopback;
description
"All ingress traffic received on the interface is internally
looped back within the interface to the egress path.";
reference "RFC XXXX, Section 2.4";
}
identity connector {
base loopback;
description
"The interface has a physical loopback connector attached that
loops all egress traffic back into the interface's ingress
path, with equivalent semantics to loopback internal.";
reference "RFC XXXX, Section 2.4";
}
identity forwarding-mode {
description "Base identity for forwarding-mode options.";
reference "RFC XXXX, Section 2.7";
}
identity physical {
base forwarding-mode;
description
"Physical layer forwarding. This includes DWDM or OTN based
optical switching.";
reference "RFC XXXX, Section 2.7";
}
identity data-link {
base forwarding-mode;
description
"Layer 2 based forwarding, such as Ethernet/VLAN based
switching, or L2VPN services.";
reference "RFC XXXX, Section 2.7";
}
identity network {
base forwarding-mode;
description
"Network layer based forwarding, such as IP, MPLS, or L3VPNs.";
reference "RFC XXXX, Section 2.7";
}
/*
* Augments the IETF interfaces model with leaves to configure
* and monitor link-flap-suppression on an interface.
*/
augment "/if:interfaces/if:interface" {
description
"Augments the IETF interface model with optional common
interface level commands that are not formally covered by any
specific standard.";
/*
* Defines standard YANG for the Link Flap Suppression feature.
*/
container link-flap-suppression {
if-feature "link-flap-suppression";
description
"Holds link flap related feature configuration.";
leaf down {
type uint32;
units milliseconds;
description
"Delays the propagation of a 'loss of carrier signal' event
that would cause the interface state to go down, i.e. the
command allows short link flaps to be suppressed. The
configured value indicates the minimum time interval (in
milliseconds) that the link signal must be continuously
down before the interface state is brought down. If not
configured, the behavior on loss of link signal is
vendor/interface specific, but with the general
expectation that there should be little or no delay.";
}
leaf up {
type uint32;
units milliseconds;
description
"Defines the minimum time interval (in milliseconds) that
the link signal must be continuously present and error
free before the interface state is allowed to transition
from down to up. If not configured, the behavior is
vendor/interface specific, but with the general
expectation that sufficient default delay should be used
to ensure that the interface is stable when enabled before
being reported as being up. Configured values that are
too low for the hardware capabilties may be rejected.";
}
leaf carrier-transitions {
type yang:counter64;
units transitions;
config false;
description
"Defines the number of times the underlying link state
has changed to, or from, state up. This counter should be
incremented even if the high layer interface state changes
are being suppressed by a running link flap suppression
timer.";
}
leaf timer-running {
type enumeration {
enum none {
description
"No link flap suppression timer is running.";
}
enum up {
description
"link-flap-suppression up timer is running. The
underlying link state is up, but interface state is
not reported as up.";
}
enum down {
description
"link-flap-suppression down timer is running.
Interface state is reported as up, but the underlying
link state is actually down.";
}
}
config false;
description
"Reports whether a link flap suppression timer is actively
running, in which case the interface state does not match
the underlying link state.";
}
reference "RFC XXXX, Section 2.1 Link Flap Suppression";
}
/*
* Augments the IETF interfaces model with a container to hold
* generic interface dampening
*/
container dampening {
if-feature "dampening";
presence
"Enable interface link flap dampening with default settings
(that are vendor/device specific).";
description
"Interface dampening limits the propagation of interface link
state flaps over longer periods.";
reference "RFC XXXX, Section 2.2 Dampening";
leaf half-life {
type uint32;
units seconds;
description
"The time (in seconds) after which a penalty would be half
its original value. Once the interface has been assigned
a penalty, the penalty is decreased at a decay rate
equivalent to the half-life. For some devices, the
allowed values may be restricted to particular multiples
of seconds. The default value is vendor/device
specific.";
reference "RFC XXXX, Section 2.3.2 Half-Life Period";
}
leaf reuse {
type uint32;
description
"Penalty value below which a stable interface is
unsuppressed (i.e. brought up) (no units). The default
value is vendor/device specific. The penalty value for a
link up->down state change is 1000 units.";
reference "RFC XXXX, Section 2.2.3 Reuse Threshold";
}
leaf suppress {
type uint32;
description
"Limit at which an interface is suppressed (i.e. held down)
when its penalty exceeds that limit (no units). The value
must be greater than the reuse threshold. The default
value is vendor/device specific. The penalty value for a
link up->down state change is 1000 units.";
reference "RFC XXXX, Section 2.2.1 Suppress Threshold";
}
leaf max-suppress-time {
type uint32;
units seconds;
description
"Maximum time (in seconds) that an interface can be
suppressed before being unsuppressed if no further link
up->down state change penalties have been applied. This
value effectively acts as a ceiling that the penalty value
cannot exceed. The default value is vendor/device
specific.";
reference "RFC XXXX, Section 2.2.4 Maximum Suppress Time";
}
leaf penalty {
type uint32;
config false;
description
"The current penalty value for this interface. When the
penalty value exceeds the 'suppress' leaf then the
interface is suppressed (i.e. held down).";
reference "RFC XXXX, Section 2.2 Dampening";
}
leaf suppressed {
type boolean;
config false;
description
"Represents whether the interface is suppressed (i.e. held
down) because the 'penalty' leaf value exceeds the
'suppress' leaf.";
reference "RFC XXXX, Section 2.2 Dampening";
}
leaf time-remaining {
when '../suppressed = "true"' {
description
"Only suppressed interfaces have a time remaining.";
}
type uint32;
units seconds;
config false;
description
"For a suppressed interface, this leaf represents how long
(in seconds) that the interface will remain suppressed
before it is allowed to go back up again.";
reference "RFC XXXX, Section 2.2 Dampening";
}
}
/*
* Various types of interfaces support a configurable layer 2
* encapsulation, any that are supported by YANG should be
* listed here.
*
* Different encapsulations can hook into the common encaps-type
* choice statement.
*/
container encapsulation {
when
"derived-from-or-self(../if:type,
'ianaift:ethernetCsmacd') or
derived-from-or-self(../if:type,
'ianaift:ieee8023adLag') or
derived-from-or-self(../if:type, 'ianaift:pos') or
derived-from-or-self(../if:type,
'ianaift:atmSubInterface') or
derived-from-or-self(../if:type, 'ianaift:l2vlan') or
derived-from-or-self(../if:type, 'ethSubInterface')" {
description
"All interface types that can have a configurable L2
encapsulation.";
}
description
"Holds the OSI layer 2 encapsulation associated with an
interface.";
choice encaps-type {
description
"Extensible choice of layer 2 encapsulations";
reference "RFC XXXX, Section 2.3 Encapsulation";
}
}
/*
* Various types of interfaces support loopback configuration,
* any that are supported by YANG should be listed here.
*/
leaf loopback {
when "derived-from-or-self(../if:type,
'ianaift:ethernetCsmacd') or
derived-from-or-self(../if:type, 'ianaift:sonet') or
derived-from-or-self(../if:type, 'ianaift:atm') or
derived-from-or-self(../if:type, 'ianaift:otnOtu')" {
description
"All interface types that support loopback configuration.";
}
if-feature "loopback";
type identityref {
base loopback;
}
description "Enables traffic loopback.";
reference "RFC XXXX, Section 2.4 Loopback";
}
/*
* Allows the maximum frame size to be configured or reported.
*/
leaf max-frame-size {
if-feature "max-frame-size";
type uint32 {
range "64 .. max";
}
description
"The maximum size of layer 2 frames that may be transmitted
or received on the interface (including any frame header,
maximum frame payload size, and frame checksum sequence).
If configured, the max-frame-size also limits the maximum
frame size of any child sub-interfaces. The MTU available
to higher layer protocols is restricted to the maximum frame
payload size, and MAY be further restricted by explicit
layer 3 or protocol specific MTU configuration.";
reference "RFC XXXX, Section 2.5 Maximum Frame Size";
}
/*
* Augments the IETF interfaces model with a leaf that indicates
* which mode, or layer, is being used to forward the traffic.
*/
leaf forwarding-mode {
type identityref {
base forwarding-mode;
}
config false;
description
"The forwarding mode that the interface is operating in.";
reference "RFC XXXX, Section 2.7 Forwarding Mode";
}
}
/*
* Add generic support for sub-interfaces.
*
* This should be extended to cover all interface types that are
* child interfaces of other interfaces.
*/
augment "/if:interfaces/if:interface" {
when "derived-from(if:type, 'sub-interface') or
derived-from-or-self(if:type, 'ianaift:l2vlan') or
derived-from-or-self(if:type, 'ianaift:atmSubInterface') or
derived-from-or-self(if:type, 'ianaift:frameRelay')" {
description
"Any ianaift:types that explicitly represent sub-interfaces
or any types that derive from the sub-interface identity.";
}
if-feature "sub-interfaces";
description
"Adds a parent interface field to interfaces that model
sub-interfaces.";
leaf parent-interface {
type if:interface-ref;
mandatory true;
description
"This is the reference to the parent interface of this
sub-interface.";
reference "RFC XXXX, Section 2.6 Sub-interface";
}
}
/*
* Add discard counter for unknown sub-interface encapsulation
*/
augment "/if:interfaces/if:interface/if:statistics" {
when "derived-from-or-self(../if:type,
'ianaift:ethernetCsmacd') or
derived-from-or-self(../if:type,
'ianaift:ieee8023adLag') or
derived-from-or-self(../if:type, 'ianaift:ifPwType')" {
description
"Applies to interfaces that can demultiplex ingress frames to
sub-interfaces.";
}
if-feature "sub-interfaces";
description
"Augment the interface model statistics with a sub-interface
demux discard counter.";
leaf in-discard-unknown-encaps {
type yang:counter64;
units frames;
description
"A count of the number of frames that were well formed, but
otherwise discarded because their encapsulation does not
classify the frame to the interface or any child
sub-interface. E.g., a frame might be discarded because the
it has an unknown VLAN Id, or does not have a VLAN Id when
one is expected.
For consistency, frames counted against this counter are
also counted against the IETF interfaces statistics. In
particular, they are included in in-octets and in-discards,
but are not included in in-unicast-pkts, in-multicast-pkts
or in-broadcast-pkts, because they are not delivered to a
higher layer.
Discontinuities in the values of this counter can occur at
re-initialization of the management system, and at other
times as indicated by the value of the 'discontinuity-time'
leaf defined in the ietf-interfaces YANG module
(RFC 8343).";
}
}
}
@@ -0,0 +1,49 @@
submodule infix-if-vlan {
yang-version 1.1;
belongs-to infix-interfaces {
prefix infix-if;
}
import ietf-interfaces {
prefix if;
}
import infix-if-type {
prefix infixift;
}
import ieee802-dot1q-types {
prefix dot1q-types;
}
contact "kernelkit@googlegroups.com";
description
"This module implements VLAN (8021q) encapsulation";
revision 2023-10-25 {
description "Initial revision";
}
augment "/if:interfaces/if:interface" {
when "derived-from-or-self(if:type, 'infixift:vlan')" {
description "Only shown for if:type vlan";
}
description "Augment to add 802.1Q VLAN tag classifications";
container vlan {
description "Configure 802.1q/802.1ad VLANs";
leaf tag-type {
type dot1q-types:dot1q-tag-type;
default dot1q-types:c-vlan;
description "VLAN type";
}
leaf id {
type dot1q-types:vlanid;
mandatory true;
description "VLAN Id";
}
leaf lower-layer-if {
type if:interface-ref;
mandatory true;
description "Base interface for VLAN";
}
}
}
}
@@ -13,6 +13,7 @@ module infix-interfaces {
include infix-if-base;
include infix-if-bridge;
include infix-if-veth;
include infix-if-vlan;
organization "KernelKit";
contact "kernelkit@googlegroups.com";
+20 -5
View File
@@ -254,9 +254,10 @@ static int ip_link_kind_is_dsa(json_t *j_iface)
static int ly_add_ip_link_parent(const struct ly_ctx *ctx, struct lyd_node **parent,
char *xpath, json_t *j_iface)
{
struct lyd_node *vlan_node;
char *vlan_xpath;
json_t *j_val;
int err;
j_val = json_object_get(j_iface, "link");
if (!j_val) {
/* Interface has no parent */
@@ -272,15 +273,29 @@ static int ly_add_ip_link_parent(const struct ly_ctx *ctx, struct lyd_node **par
ERROR("Expected a JSON string for 'link'");
return SR_ERR_SYS;
}
err = asprintf(&vlan_xpath, "%s/infix-interfaces:vlan", xpath);
if (err == -1) {
ERROR("Error, creating vlan xpath");
return SR_ERR_SYS;
}
err = lydx_new_path(ctx, parent, xpath,
"ietf-if-extensions:parent-interface", "%s",
json_string_value(j_val));
err = lyd_new_path(*parent, ctx, vlan_xpath, NULL, 0, &vlan_node);
if (err) {
ERROR("Error, adding 'link' to data tree, libyang error %d", err);
ERROR("Failed adding 'lower-layer-if' node (%s), libyang error %d: %s",
vlan_xpath, err, ly_errmsg(ctx));
free(vlan_xpath);
return SR_ERR_LY;
}
err = lydx_new_path(ctx, &vlan_node, vlan_xpath, "lower-layer-if",
"%s", json_string_value(j_val));
if (err) {
ERROR("Error, adding 'lower-layer-if' to data tree, libyang error %d", err);
free(vlan_xpath);
return SR_ERR_LY;
}
free(vlan_xpath);
return SR_ERR_OK;
}
+3 -8
View File
@@ -21,14 +21,9 @@ with infamy.Test() as test:
{
"name": f"{tport}.10",
"type": "infix-if-type:vlan",
"parent-interface": tport,
"encapsulation": {
"dot1q-vlan": {
"outer-tag": {
"tag-type": "ieee802-dot1q-types:c-vlan",
"vlan-id": 10,
}
}
"vlan": {
"id": 10,
"lower-layer-if": tport,
},
"ipv4": {
+3 -8
View File
@@ -41,14 +41,9 @@ with infamy.Test() as test:
"name": "vlan10",
"type": "infix-if-type:vlan",
"enabled": True,
"parent-interface": "br0",
"encapsulation": {
"dot1q-vlan": {
"outer-tag": {
"tag-type": "ieee802-dot1q-types:c-vlan",
"vlan-id": 10,
}
}
"vlan": {
"lower-layer-if": "br0",
"id": 10,
},
"ipv4": {
"address": [