diff --git a/board/netconf/rootfs/lib/infix/cli-pretty b/board/netconf/rootfs/lib/infix/cli-pretty index eaeecdad6..d05075b5d 100755 --- a/board/netconf/rootfs/lib/infix/cli-pretty +++ b/board/netconf/rootfs/lib/infix/cli-pretty @@ -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 diff --git a/src/confd/bin/bootstrap b/src/confd/bin/bootstrap index 1d30829b7..f16c77a5f 100755 --- a/src/confd/bin/bootstrap +++ b/src/confd/bin/bootstrap @@ -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 \ diff --git a/src/confd/src/ietf-interfaces.c b/src/confd/src/ietf-interfaces.c index 4eba89c1c..c044d4a6a 100644 --- a/src/confd/src/ietf-interfaces.c +++ b/src/confd/src/ietf-interfaces.c @@ -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); + + err = dagger_add_dep(net, ifname, lower_if); + if (err) + return ERR_IFACE(cif, err, "Unable to add dep \"%s\"", lower_if); - fprintf(ip, "link add dev %s down link %s type vlan", ifname, parent); - 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; /* diff --git a/src/confd/yang/ietf-if-extensions@2023-01-26.yang b/src/confd/yang/ietf-if-extensions@2023-01-26.yang deleted file mode 100644 index fdcb0bcc0..000000000 --- a/src/confd/yang/ietf-if-extensions@2023-01-26.yang +++ /dev/null @@ -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: - WG List: - - Editor: Robert Wilton - "; - - 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)."; - } - } -} diff --git a/src/confd/yang/infix-if-vlan@2023-10-25.yang b/src/confd/yang/infix-if-vlan@2023-10-25.yang new file mode 100644 index 000000000..b8993c4da --- /dev/null +++ b/src/confd/yang/infix-if-vlan@2023-10-25.yang @@ -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"; + } + } + } +} diff --git a/src/confd/yang/infix-interfaces@2023-09-19.yang b/src/confd/yang/infix-interfaces@2023-09-19.yang index 99c55ac48..1fe5496e9 100644 --- a/src/confd/yang/infix-interfaces@2023-09-19.yang +++ b/src/confd/yang/infix-interfaces@2023-09-19.yang @@ -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"; diff --git a/src/statd/iface-ip-link.c b/src/statd/iface-ip-link.c index 05ebf501c..a719c9cda 100644 --- a/src/statd/iface-ip-link.c +++ b/src/statd/iface-ip-link.c @@ -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 = lyd_new_path(*parent, ctx, vlan_xpath, NULL, 0, &vlan_node); + if (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, parent, xpath, - "ietf-if-extensions:parent-interface", "%s", - json_string_value(j_val)); + err = lydx_new_path(ctx, &vlan_node, vlan_xpath, "lower-layer-if", + "%s", json_string_value(j_val)); if (err) { - ERROR("Error, adding 'link' to data tree, libyang error %d", 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; } diff --git a/test/case/ietf_interfaces/vlan_ping.py b/test/case/ietf_interfaces/vlan_ping.py index f441c72b9..e20bdf41f 100755 --- a/test/case/ietf_interfaces/vlan_ping.py +++ b/test/case/ietf_interfaces/vlan_ping.py @@ -21,14 +21,9 @@ { "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": { diff --git a/test/case/infix_interfaces/bridge_vlan.py b/test/case/infix_interfaces/bridge_vlan.py index cfe607d73..f7505cd93 100755 --- a/test/case/infix_interfaces/bridge_vlan.py +++ b/test/case/infix_interfaces/bridge_vlan.py @@ -41,14 +41,9 @@ "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": [