mirror of
https://github.com/kernelkit/infix.git
synced 2026-07-22 09:13:01 +02:00
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:
committed by
Joachim Wiberg
parent
be8bad9885
commit
941fc31581
@@ -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
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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": [
|
||||
|
||||
Reference in New Issue
Block a user