mirror of
https://github.com/kernelkit/infix.git
synced 2026-08-01 05: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.in_octets = ''
|
||||||
self.out_octets = ''
|
self.out_octets = ''
|
||||||
|
|
||||||
self.parent = data.get('ietf-if-extensions:parent-interface', None)
|
|
||||||
|
|
||||||
if self.data.get('ietf-ip:ipv4'):
|
if self.data.get('ietf-ip:ipv4'):
|
||||||
self.mtu = self.data.get('ietf-ip:ipv4').get('mtu', '')
|
self.mtu = self.data.get('ietf-ip:ipv4').get('mtu', '')
|
||||||
self.ipv4_addr = self.data.get('ietf-ip:ipv4').get('address', '')
|
self.ipv4_addr = self.data.get('ietf-ip:ipv4').get('address', '')
|
||||||
@@ -75,6 +73,11 @@ class Iface:
|
|||||||
else:
|
else:
|
||||||
self.bridge = ''
|
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):
|
def is_vlan(self):
|
||||||
return self.data['type'] == "infix-if-type:vlan"
|
return self.data['type'] == "infix-if-type:vlan"
|
||||||
|
|
||||||
@@ -136,7 +139,7 @@ class Iface:
|
|||||||
self.pr_name(pipe="")
|
self.pr_name(pipe="")
|
||||||
self.pr_proto_eth()
|
self.pr_proto_eth()
|
||||||
|
|
||||||
if self.parent:
|
if self.lower_if:
|
||||||
self.pr_proto_ipv4(pipe='│')
|
self.pr_proto_ipv4(pipe='│')
|
||||||
self.pr_proto_ipv6(pipe='│')
|
self.pr_proto_ipv6(pipe='│')
|
||||||
else:
|
else:
|
||||||
@@ -144,7 +147,7 @@ class Iface:
|
|||||||
self.pr_proto_ipv6()
|
self.pr_proto_ipv6()
|
||||||
return
|
return
|
||||||
|
|
||||||
parent = find_iface(_ifaces, self.parent)
|
parent = find_iface(_ifaces, self.lower_if)
|
||||||
if not parent:
|
if not parent:
|
||||||
print(f"Error, didn't find parent interface for vlan {self.name}")
|
print(f"Error, didn't find parent interface for vlan {self.name}")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
@@ -227,7 +230,7 @@ def pr_interface_list(json):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
# These interfaces are printed by there parent, such as bridge
|
# These interfaces are printed by there parent, such as bridge
|
||||||
if iface.parent:
|
if iface.lower_if:
|
||||||
continue
|
continue
|
||||||
if iface.bridge:
|
if iface.bridge:
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -147,11 +147,7 @@ sysrepoctl -s $SEARCH \
|
|||||||
-i ietf-yang-push@2019-09-09.yang -g wheel -p 0660 \
|
-i ietf-yang-push@2019-09-09.yang -g wheel -p 0660 \
|
||||||
-e on-change \
|
-e on-change \
|
||||||
-i iana-if-type@2023-01-26.yang -g wheel -p 0660 \
|
-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 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-ip@2023-09-14.yang -g wheel -p 0660 \
|
||||||
-i infix-if-type@2023-08-21.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 \
|
-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;
|
goto out_free_ifname;
|
||||||
|
|
||||||
err = srx_nitems(session, &cnt,
|
err = srx_nitems(session, &cnt,
|
||||||
"%s/ietf-if-extensions:parent-interface", xpath);
|
"%s/infix-if-vlan:vlan"
|
||||||
|
"/lower-layer-if", xpath);
|
||||||
if (!err && !cnt) {
|
if (!err && !cnt) {
|
||||||
inferred.data.string_val = ifname;
|
inferred.data.string_val = ifname;
|
||||||
err = srx_set_item(session, &inferred, 0,
|
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)
|
if (err)
|
||||||
goto out_free_ifname;
|
goto out_free_ifname;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = srx_nitems(session, &cnt,
|
err = srx_nitems(session, &cnt,
|
||||||
"%s"
|
"%s/infix-if-vlan:vlan"
|
||||||
"/ietf-if-extensions:encapsulation"
|
"/tag-type", xpath);
|
||||||
"/ietf-if-vlan-encapsulation:dot1q-vlan"
|
|
||||||
"/outer-tag/tag-type", xpath);
|
|
||||||
if (!err && !cnt) {
|
if (!err && !cnt) {
|
||||||
inferred.data.string_val = "ieee802-dot1q-types:c-vlan";
|
inferred.data.string_val = "ieee802-dot1q-types:c-vlan";
|
||||||
err = srx_set_item(session, &inferred, 0,
|
err = srx_set_item(session, &inferred, 0,
|
||||||
"%s"
|
"%s/infix-if-vlan:vlan"
|
||||||
"/ietf-if-extensions:encapsulation"
|
"/tag-type", xpath);
|
||||||
"/ietf-if-vlan-encapsulation:dot1q-vlan"
|
|
||||||
"/outer-tag/tag-type", xpath);
|
|
||||||
if (err)
|
if (err)
|
||||||
goto out_free_ifname;
|
goto out_free_ifname;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = srx_nitems(session, &cnt,
|
err = srx_nitems(session, &cnt,
|
||||||
"%s"
|
"%s/infix-if-vlan:vlan"
|
||||||
"/ietf-if-extensions:encapsulation"
|
"/id", xpath);
|
||||||
"/ietf-if-vlan-encapsulation:dot1q-vlan"
|
|
||||||
"/outer-tag/vlan-id", xpath);
|
|
||||||
if (!err && !cnt) {
|
if (!err && !cnt) {
|
||||||
inferred.data.string_val = vidstr;
|
inferred.data.string_val = vidstr;
|
||||||
err = srx_set_item(session, &inferred, 0,
|
err = srx_set_item(session, &inferred, 0,
|
||||||
"%s"
|
"%s/infix-if-vlan:vlan"
|
||||||
"/ietf-if-extensions:encapsulation"
|
"/id", xpath);
|
||||||
"/ietf-if-vlan-encapsulation:dot1q-vlan"
|
|
||||||
"/outer-tag/vlan-id", xpath);
|
|
||||||
if (err)
|
if (err)
|
||||||
goto out_free_ifname;
|
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,
|
static int netdag_gen_vlan(struct dagger *net, struct lyd_node *dif,
|
||||||
struct lyd_node *cif, FILE *ip)
|
struct lyd_node *cif, FILE *ip)
|
||||||
{
|
{
|
||||||
const char *parent = lydx_get_cattr(cif, "parent-interface");
|
|
||||||
const char *ifname = lydx_get_cattr(cif, "name");
|
const char *ifname = lydx_get_cattr(cif, "name");
|
||||||
struct lydx_diff typed, vidd;
|
struct lydx_diff typed, vidd;
|
||||||
struct lyd_node *otag;
|
struct lyd_node *vlan;
|
||||||
|
const char *lower_if;
|
||||||
const char *proto;
|
const char *proto;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
DEBUG("ifname %s parent %s", ifname, parent);
|
vlan = lydx_get_descendant(lyd_child(dif ? : cif), "vlan", NULL);
|
||||||
|
if (!vlan) {
|
||||||
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) {
|
|
||||||
/*
|
/*
|
||||||
* 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
|
* from cif, otherwise it just means the interface had a
|
||||||
* a change that was not related to the VLAN config.
|
* a change that was not related to the VLAN config.
|
||||||
*/
|
*/
|
||||||
if (!dif)
|
if (!dif)
|
||||||
ERROR("%s: missing mandatory outer-tag", ifname);
|
ERROR("%s: missing mandatory vlan", ifname);
|
||||||
return 0;
|
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);
|
proto = bridge_tagtype2str(typed.new);
|
||||||
if (!proto)
|
if (!proto)
|
||||||
return ERR_IFACE(cif, -ENOSYS, "Unsupported tag type \"%s\"", typed.new);
|
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);
|
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);
|
fprintf(ip, " id %s", vidd.new);
|
||||||
|
|
||||||
fputc('\n', ip);
|
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");
|
const char *iftype = lydx_get_cattr(cif, "type");
|
||||||
|
|
||||||
if (!strcmp(iftype, "infix-if-type:bridge")) {
|
if (strcmp(iftype, "infix-if-type:ethernet")) {
|
||||||
if (is_phys_addr_deleted(dif))
|
|
||||||
return true;
|
|
||||||
} else if (!strcmp(iftype, "infix-if-type:vlan")) {
|
|
||||||
if (is_phys_addr_deleted(dif))
|
if (is_phys_addr_deleted(dif))
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (lydx_get_cattr(dif, "parent-interface") ||
|
if (!strcmp(iftype, "infix-if-type:vlan")) {
|
||||||
lydx_get_descendant(lyd_child(dif),
|
if (lydx_get_descendant(lyd_child(dif), "vlan", NULL))
|
||||||
"encapsulation",
|
|
||||||
"dot1q-vlan",
|
|
||||||
"outer-tag",
|
|
||||||
NULL))
|
|
||||||
return true;
|
return true;
|
||||||
} else if (!strcmp(iftype, "infix-if-type:veth")) {
|
} 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))
|
if (lydx_get_descendant(lyd_child(dif), "peer", NULL))
|
||||||
return true;
|
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-base;
|
||||||
include infix-if-bridge;
|
include infix-if-bridge;
|
||||||
include infix-if-veth;
|
include infix-if-veth;
|
||||||
|
include infix-if-vlan;
|
||||||
|
|
||||||
organization "KernelKit";
|
organization "KernelKit";
|
||||||
contact "kernelkit@googlegroups.com";
|
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,
|
static int ly_add_ip_link_parent(const struct ly_ctx *ctx, struct lyd_node **parent,
|
||||||
char *xpath, json_t *j_iface)
|
char *xpath, json_t *j_iface)
|
||||||
{
|
{
|
||||||
|
struct lyd_node *vlan_node;
|
||||||
|
char *vlan_xpath;
|
||||||
json_t *j_val;
|
json_t *j_val;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
j_val = json_object_get(j_iface, "link");
|
j_val = json_object_get(j_iface, "link");
|
||||||
if (!j_val) {
|
if (!j_val) {
|
||||||
/* Interface has no parent */
|
/* 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'");
|
ERROR("Expected a JSON string for 'link'");
|
||||||
return SR_ERR_SYS;
|
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,
|
err = lyd_new_path(*parent, ctx, vlan_xpath, NULL, 0, &vlan_node);
|
||||||
"ietf-if-extensions:parent-interface", "%s",
|
|
||||||
json_string_value(j_val));
|
|
||||||
if (err) {
|
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;
|
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;
|
return SR_ERR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,14 +21,9 @@ with infamy.Test() as test:
|
|||||||
{
|
{
|
||||||
"name": f"{tport}.10",
|
"name": f"{tport}.10",
|
||||||
"type": "infix-if-type:vlan",
|
"type": "infix-if-type:vlan",
|
||||||
"parent-interface": tport,
|
"vlan": {
|
||||||
"encapsulation": {
|
"id": 10,
|
||||||
"dot1q-vlan": {
|
"lower-layer-if": tport,
|
||||||
"outer-tag": {
|
|
||||||
"tag-type": "ieee802-dot1q-types:c-vlan",
|
|
||||||
"vlan-id": 10,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
"ipv4": {
|
"ipv4": {
|
||||||
|
|||||||
@@ -41,14 +41,9 @@ with infamy.Test() as test:
|
|||||||
"name": "vlan10",
|
"name": "vlan10",
|
||||||
"type": "infix-if-type:vlan",
|
"type": "infix-if-type:vlan",
|
||||||
"enabled": True,
|
"enabled": True,
|
||||||
"parent-interface": "br0",
|
"vlan": {
|
||||||
"encapsulation": {
|
"lower-layer-if": "br0",
|
||||||
"dot1q-vlan": {
|
"id": 10,
|
||||||
"outer-tag": {
|
|
||||||
"tag-type": "ieee802-dot1q-types:c-vlan",
|
|
||||||
"vlan-id": 10,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"ipv4": {
|
"ipv4": {
|
||||||
"address": [
|
"address": [
|
||||||
|
|||||||
Reference in New Issue
Block a user