Skip to content

Add multicast-focused AFTs#1468

Open
bewing wants to merge 1 commit into
openconfig:masterfrom
bewing:feat/mft
Open

Add multicast-focused AFTs#1468
bewing wants to merge 1 commit into
openconfig:masterfrom
bewing:feat/mft

Conversation

@bewing

@bewing bewing commented Apr 2, 2026

Copy link
Copy Markdown
Contributor

As an operator, I need a standard way to monitor the current forwarding behavior of multicast on my network, across multiple vendor types.

Most(?) platforms forward multicast under a input interface / OIL model, keyed by various FECs. This change attempts to provide an initial implementation for IPv4, IPv6, and MPLS forwarding of multicast traffic.

Change Scope

  • Add multicast-focused AFTs
  • This change only adds new AFTs, and should be backwards compatible with existing implementations of AFT

Platform Implementations

Tree View

--- /home/bewing/old-tree.txt   2026-05-20 11:44:22.678265610 -0500
+++ /home/bewing/new-tree.txt   2026-05-20 12:50:19.973577532 -0500
@@ -3853,390 +3853,475 @@
         |  |        +--rw next-hop* [index]
         |  |           +--rw index     -> ../config/index
         |  |           +--rw config
         |  |           |  +--rw index?   -> ../../../../../../next-hops/next-hop/index
         |  |           +--ro state
         |  |              +--ro index?   -> ../../../../../../next-hops/next-hop/index
         |  +--rw next-hops
         |     +--rw next-hop* [index]
         |        +--rw index            -> ../config/index
         |        +--rw config
         |        |  +--rw index?                                     string
         |        |  +--rw next-hop?                                  union
         |        |  +--rw recurse?                                   boolean
         |        |  +--rw metric?                                    uint32
         |        |  +--rw preference?                                uint32
         |        |  +--rw wecmp-weight?                              union
         |        |  +--rw oc-loc-rt-netinst:next-network-instance?   -> /oc-ni:network-instances/network-instance/config/name
         |        |  +--rw oc-loc-rt-netinst:nh-network-instance?     -> /oc-ni:network-instances/network-instance/config/name
         |        +--ro state
         |        |  +--ro index?                                     string
         |        |  +--ro next-hop?                                  union
         |        |  +--ro recurse?                                   boolean
         |        |  +--ro metric?                                    uint32
         |        |  +--ro preference?                                uint32
         |        |  +--ro wecmp-weight?                              union
         |        |  +--ro oc-loc-rt-netinst:next-network-instance?   -> /oc-ni:network-instances/network-instance/config/name
         |        |  +--ro oc-loc-rt-netinst:nh-network-instance?     -> /oc-ni:network-instances/network-instance/config/name
         |        +--rw encap-headers
         |           +--rw encap-header* [index]
         |              +--rw index     -> ../config/index
         |              +--rw config
         |              |  +--rw index?   uint8
         |              |  +--rw type?    oc-aftt:encapsulation-header-type
         |              +--ro state
         |              |  +--ro index?   uint8
         |              |  +--ro type?    oc-aftt:encapsulation-header-type
         |              +--rw udp-v4
         |              |  +--rw config
         |              |  |  +--rw src-ip?         oc-inet:ipv4-address
         |              |  |  +--rw dst-ip?         oc-inet:ipv4-address
         |              |  |  +--rw dscp?           oc-inet:dscp
         |              |  |  +--rw src-udp-port?   oc-inet:port-number
         |              |  |  +--rw dst-udp-port?   oc-inet:port-number
         |              |  |  +--rw ip-ttl?         uint8
         |              |  +--ro state
         |              |     +--ro src-ip?         oc-inet:ipv4-address
         |              |     +--ro dst-ip?         oc-inet:ipv4-address
         |              |     +--ro dscp?           oc-inet:dscp
         |              |     +--ro src-udp-port?   oc-inet:port-number
         |              |     +--ro dst-udp-port?   oc-inet:port-number
         |              |     +--ro ip-ttl?         uint8
         |              +--rw gre
         |              |  +--rw config
         |              |  |  +--rw src-ip?   oc-inet:ip-address
         |              |  |  +--rw dst-ip?   oc-inet:ip-address
         |              |  |  +--rw ttl?      uint8
         |              |  +--ro state
         |              |     +--ro src-ip?   oc-inet:ip-address
         |              |     +--ro dst-ip?   oc-inet:ip-address
         |              |     +--ro ttl?      uint8
         |              +--rw mpls
         |                 +--rw config
         |                 |  +--rw traffic-class?   oc-mplst:mpls-tc
         |                 |  +--rw label?           oc-mplst:mpls-label
         |                 +--ro state
         |                    +--ro traffic-class?   oc-mplst:mpls-tc
         |                    +--ro label?           oc-mplst:mpls-label
         +--rw afts
         |  +--ro ipv4-unicast
         |  |  +--ro ipv4-entry* [prefix]
         |  |     +--ro prefix    -> ../state/prefix
         |  |     +--ro state
         |  |        +--ro prefix?                                     oc-inet:ipv4-prefix
         |  |        +--ro counters
         |  |        |  x--ro packets-forwarded?          oc-yang:counter64
         |  |        |  x--ro octets-forwarded?           oc-yang:counter64
         |  |        |  x--ro packets-forwarded-backup?   oc-yang:counter64
         |  |        |  x--ro octets-forwarded-backup?    oc-yang:counter64
         |  |        +--ro entry-metadata?                             binary
         |  |        +--ro origin-protocol?                            identityref
         |  |        +--ro decapsulate-header?                         oc-aftt:encapsulation-header-type
         |  |        +--ro oc-aftni:next-hop-group?                    -> /oc-ni:network-instances/network-instance/afts/next-hop-groups/next-hop-group/state/id
         |  |        +--ro oc-aftni:next-hop-group-network-instance?   oc-ni:network-instance-ref
         |  |        +--ro oc-aftni:origin-network-instance?           oc-ni:network-instance-ref
         |  +--ro ipv6-unicast
         |  |  +--ro ipv6-entry* [prefix]
         |  |     +--ro prefix    -> ../state/prefix
         |  |     +--ro state
         |  |        +--ro prefix?                                     oc-inet:ipv6-prefix
         |  |        +--ro counters
         |  |        |  x--ro packets-forwarded?          oc-yang:counter64
         |  |        |  x--ro octets-forwarded?           oc-yang:counter64
         |  |        |  x--ro packets-forwarded-backup?   oc-yang:counter64
         |  |        |  x--ro octets-forwarded-backup?    oc-yang:counter64
         |  |        +--ro entry-metadata?                             binary
         |  |        +--ro origin-protocol?                            identityref
         |  |        +--ro decapsulate-header?                         oc-aftt:encapsulation-header-type
         |  |        +--ro oc-aftni:next-hop-group?                    -> /oc-ni:network-instances/network-instance/afts/next-hop-groups/next-hop-group/state/id
         |  |        +--ro oc-aftni:next-hop-group-network-instance?   oc-ni:network-instance-ref
         |  |        +--ro oc-aftni:origin-network-instance?           oc-ni:network-instance-ref
+        |  +--ro ipv4-multicast
+        |  |  +--ro ipv4-multicast-entry* [source-address group-address]
+        |  |     +--ro source-address    -> ../state/source-address
+        |  |     +--ro group-address     -> ../state/group-address
+        |  |     +--ro state
+        |  |        +--ro source-address?                             oc-inet:ipv4-address
+        |  |        +--ro group-address?                              oc-inet:ipv4-address
+        |  |        +--ro counters
+        |  |        |  x--ro packets-forwarded?   oc-yang:counter64
+        |  |        |  x--ro octets-forwarded?    oc-yang:counter64
+        |  |        +--ro entry-metadata?                             binary
+        |  |        +--ro origin-protocol?                            identityref
+        |  |        +--ro decapsulate-header?                         oc-aftt:encapsulation-header-type
+        |  |        +--ro reverse-path-interface
+        |  |        |  +--ro interface-ref
+        |  |        |     +--ro state
+        |  |        |        +--ro interface?      -> /oc-if:interfaces/interface/name
+        |  |        |        +--ro subinterface?   -> /oc-if:interfaces/interface[oc-if:name=current()/../interface]/subinterfaces/subinterface/index
+        |  |        +--ro oc-aftni:next-hop-group?                    -> /oc-ni:network-instances/network-instance/afts/next-hop-groups/next-hop-group/state/id
+        |  |        +--ro oc-aftni:next-hop-group-network-instance?   oc-ni:network-instance-ref
+        |  +--ro ipv6-multicast
+        |  |  +--ro ipv6-multicast-entry* [source-address group-address]
+        |  |     +--ro source-address    -> ../state/source-address
+        |  |     +--ro group-address     -> ../state/group-address
+        |  |     +--ro state
+        |  |        +--ro source-address?                             oc-inet:ipv6-address
+        |  |        +--ro group-address?                              oc-inet:ipv6-address
+        |  |        +--ro counters
+        |  |        |  x--ro packets-forwarded?   oc-yang:counter64
+        |  |        |  x--ro octets-forwarded?    oc-yang:counter64
+        |  |        +--ro entry-metadata?                             binary
+        |  |        +--ro origin-protocol?                            identityref
+        |  |        +--ro decapsulate-header?                         oc-aftt:encapsulation-header-type
+        |  |        +--ro reverse-path-interface
+        |  |        |  +--ro interface-ref
+        |  |        |     +--ro state
+        |  |        |        +--ro interface?      -> /oc-if:interfaces/interface/name
+        |  |        |        +--ro subinterface?   -> /oc-if:interfaces/interface[oc-if:name=current()/../interface]/subinterfaces/subinterface/index
+        |  |        +--ro oc-aftni:next-hop-group?                    -> /oc-ni:network-instances/network-instance/afts/next-hop-groups/next-hop-group/state/id
+        |  |        +--ro oc-aftni:next-hop-group-network-instance?   oc-ni:network-instance-ref
+        |  +--ro mpls-multicast
+        |  |  +--ro multicast-label-entry* [label]
+        |  |     +--ro label                      -> ../state/label
+        |  |     +--ro state
+        |  |     |  +--ro label?                                      oc-mplst:mpls-label
+        |  |     |  +--ro counters
+        |  |     |  |  x--ro packets-forwarded?   oc-yang:counter64
+        |  |     |  |  x--ro octets-forwarded?    oc-yang:counter64
+        |  |     |  +--ro entry-metadata?                             binary
+        |  |     |  +--ro origin-protocol?                            identityref
+        |  |     |  +--ro oc-aftni:next-hop-group?                    -> /oc-ni:network-instances/network-instance/afts/next-hop-groups/next-hop-group/state/id
+        |  |     |  +--ro oc-aftni:next-hop-group-network-instance?   oc-ni:network-instance-ref
+        |  |     +--ro decap-mpls-label-stacks
+        |  |        +--ro decap-mpls-label-stack* [id]
+        |  |           +--ro id       -> ../state/id
+        |  |           +--ro state
+        |  |              +--ro id?      uint8
+        |  |              +--ro label?   oc-mplst:mpls-label
         |  +--ro policy-forwarding
         |  |  +--ro policy-forwarding-entry* [index]
         |  |     +--ro index    -> ../state/index
         |  |     +--ro state
         |  |        +--ro index?                                      uint64
         |  |        +--ro ip-prefix?                                  oc-inet:ip-prefix
         |  |        +--ro mac-address?                                oc-yang:mac-address
         |  |        +--ro mpls-label?                                 oc-mplst:mpls-label
         |  |        +--ro mpls-tc?                                    oc-mplst:mpls-tc
         |  |        +--ro ip-dscp?                                    oc-inet:dscp
         |  |        +--ro ip-protocol?                                oc-pkt-match-types:ip-protocol-type
         |  |        +--ro l4-src-port?                                oc-inet:port-number
         |  |        +--ro l4-dst-port?                                oc-inet:port-number
         |  |        +--ro counters
         |  |        |  x--ro packets-forwarded?   oc-yang:counter64
         |  |        |  x--ro octets-forwarded?    oc-yang:counter64
         |  |        +--ro entry-metadata?                             binary
         |  |        +--ro oc-aftni:next-hop-group?                    -> /oc-ni:network-instances/network-instance/afts/next-hop-groups/next-hop-group/state/id
         |  |        +--ro oc-aftni:next-hop-group-network-instance?   oc-ni:network-instance-ref
         |  +--ro mpls
         |  |  +--ro label-entry* [label]
         |  |     +--ro label                      -> ../state/label
         |  |     +--ro state
         |  |     |  +--ro label?                                      oc-mplst:mpls-label
         |  |     |  +--ro counters
         |  |     |  |  x--ro packets-forwarded?   oc-yang:counter64
         |  |     |  |  x--ro octets-forwarded?    oc-yang:counter64
         |  |     |  +--ro entry-metadata?                             binary
         |  |     |  x--ro popped-mpls-label-stack*                    oc-mplst:mpls-label
         |  |     |  +--ro oc-aftni:next-hop-group?                    -> /oc-ni:network-instances/network-instance/afts/next-hop-groups/next-hop-group/state/id
         |  |     |  +--ro oc-aftni:next-hop-group-network-instance?   oc-ni:network-instance-ref
         |  |     +--ro decap-mpls-label-stacks
         |  |        +--ro decap-mpls-label-stack* [id]
         |  |           +--ro id       -> ../state/id
         |  |           +--ro state
         |  |              +--ro id?      uint8
         |  |              +--ro label?   oc-mplst:mpls-label
         |  +--ro ethernet
         |  |  +--ro mac-entry* [mac-address]
         |  |     +--ro mac-address    -> ../state/mac-address
         |  |     +--ro state
         |  |        +--ro mac-address?                                oc-yang:mac-address
         |  |        +--ro counters
         |  |        |  x--ro packets-forwarded?   oc-yang:counter64
         |  |        |  x--ro octets-forwarded?    oc-yang:counter64
         |  |        +--ro entry-metadata?                             binary
         |  |        +--ro oc-aftni:next-hop-group?                    -> /oc-ni:network-instances/network-instance/afts/next-hop-groups/next-hop-group/state/id
         |  |        +--ro oc-aftni:next-hop-group-network-instance?   oc-ni:network-instance-ref
         |  +--ro state-synced
         |  |  +--ro state
         |  |     +--ro ipv4-unicast?   boolean
         |  |     +--ro ipv6-unicast?   boolean
         |  +--ro next-hop-groups
         |  |  +--ro next-hop-group* [id]
         |  |     +--ro id             -> ../state/id
         |  |     +--ro state
         |  |     |  +--ro id?                      uint64
         |  |     |  +--ro next-hop-group-name?     string
         |  |     |  +--ro programmed-id?           uint64
         |  |     |  +--ro color?                   uint64
         |  |     |  +--ro backup-next-hop-group?   -> ../../../next-hop-group/state/id
         |  |     |  +--ro backup-active?           boolean
         |  |     +--ro next-hops
         |  |     |  +--ro next-hop* [index]
         |  |     |     +--ro index    -> ../state/index
         |  |     |     +--ro state
         |  |     |        +--ro index?    -> ../../../../../../next-hops/next-hop/state/index
         |  |     |        +--ro weight?   uint64
         |  |     +--ro conditional
         |  |        +--ro condition* [id]
         |  |           +--ro id                  -> ../state/id
         |  |           +--ro state
         |  |           |  +--ro id?               uint64
         |  |           |  +--ro dscp*             oc-inet:dscp
         |  |           |  +--ro next-hop-group?   -> ../../../../../next-hop-group/state/id
         |  |           +--ro input-interfaces
         |  |              +--ro input-interface* [id]
         |  |                 +--ro id       -> ../state/id
         |  |                 +--ro state
         |  |                    +--ro id?             string
         |  |                    +--ro interface?      -> /oc-if:interfaces/interface/name
         |  |                    +--ro subinterface?   -> /oc-if:interfaces/interface[oc-if:name=current()/../interface]/subinterfaces/subinterface/index
         |  +--ro next-hops
         |  |  +--ro next-hop* [index]
         |  |     +--ro index            -> ../state/index
         |  |     +--ro state
         |  |     |  +--ro index?                       uint64
         |  |     |  +--ro programmed-index?            uint64
         |  |     |  +--ro ip-address?                  oc-inet:ip-address
         |  |     |  +--ro mac-address?                 oc-yang:mac-address
         |  |     |  +--ro pop-top-label?               boolean
         |  |     |  x--ro pushed-mpls-label-stack*     oc-mplst:mpls-label
         |  |     |  +--ro encapsulate-header?          oc-aftt:encapsulation-header-type
         |  |     |  +--ro decapsulate-header?          oc-aftt:encapsulation-header-type
         |  |     |  +--ro origin-protocol?             identityref
         |  |     |  +--ro lsp-name?                    string
         |  |     |  +--ro counters
         |  |     |  |  x--ro packets-forwarded?   oc-yang:counter64
         |  |     |  |  x--ro octets-forwarded?    oc-yang:counter64
         |  |     |  +--ro vni-label?                   oc-evpn-types:evi-id
         |  |     |  +--ro tunnel-src-ip-address?       oc-inet:ip-address
         |  |     |  +--ro oc-aftni:network-instance?   oc-ni:network-instance-ref
         |  |     +--ro ip-in-ip
         |  |     |  +--ro state
         |  |     |     +--ro src-ip?   oc-inet:ip-address
         |  |     |     +--ro dst-ip?   oc-inet:ip-address
         |  |     +--ro gre
         |  |     |  +--ro state
         |  |     |     +--ro src-ip?   oc-inet:ip-address
         |  |     |     +--ro dst-ip?   oc-inet:ip-address
         |  |     |     +--ro ttl?      uint8
         |  |     +--ro encap-headers
         |  |     |  +--ro encap-header* [index]
         |  |     |     +--ro index     -> ../state/index
         |  |     |     +--ro state
         |  |     |     |  +--ro index?   uint8
         |  |     |     |  +--ro type?    oc-aftt:encapsulation-header-type
         |  |     |     +--ro gre
         |  |     |     |  +--ro state
         |  |     |     |     +--ro src-ip?   oc-inet:ip-address
         |  |     |     |     +--ro dst-ip?   oc-inet:ip-address
         |  |     |     |     +--ro ttl?      uint8
         |  |     |     +--ro ipv4
         |  |     |     |  +--ro state
         |  |     |     |     +--ro src-ip?   oc-inet:ip-address
         |  |     |     |     +--ro dst-ip?   oc-inet:ip-address
         |  |     |     +--ro ipv6
         |  |     |     |  +--ro state
         |  |     |     |     +--ro src-ip?   oc-inet:ip-address
         |  |     |     |     +--ro dst-ip?   oc-inet:ip-address
         |  |     |     +--ro mpls
         |  |     |     |  +--ro state
         |  |     |     |  |  +--ro traffic-class?      oc-mplst:mpls-tc
         |  |     |     |  |  x--ro mpls-label-stack*   oc-mplst:mpls-label
         |  |     |     |  +--ro encap-mpls-label-stacks
         |  |     |     |     +--ro encap-mpls-label-stack* [id]
         |  |     |     |        +--ro id       -> ../state/id
         |  |     |     |        +--ro state
         |  |     |     |           +--ro id?      uint8
         |  |     |     |           +--ro label?   oc-mplst:mpls-label
         |  |     |     +--ro udp-v4
         |  |     |     |  +--ro state
         |  |     |     |     +--ro src-ip?         oc-inet:ipv4-address
         |  |     |     |     +--ro dst-ip?         oc-inet:ipv4-address
         |  |     |     |     +--ro dscp?           oc-inet:dscp
         |  |     |     |     +--ro src-udp-port?   oc-inet:port-number
         |  |     |     |     +--ro dst-udp-port?   oc-inet:port-number
         |  |     |     |     +--ro ip-ttl?         uint8
         |  |     |     +--ro udp-v6
         |  |     |     |  +--ro state
         |  |     |     |     +--ro src-ip?         oc-inet:ipv6-address
         |  |     |     |     +--ro dst-ip?         oc-inet:ipv6-address
         |  |     |     |     +--ro dscp?           oc-inet:dscp
         |  |     |     |     +--ro src-udp-port?   oc-inet:port-number
         |  |     |     |     +--ro dst-udp-port?   oc-inet:port-number
         |  |     |     |     +--ro ip-ttl?         uint8
         |  |     |     +--ro vxlan
         |  |     |        +--ro state
         |  |     |           +--ro vni-label?               oc-evpn-types:evi-id
         |  |     |           +--ro tunnel-src-ip-address?   oc-inet:ip-address
         |  |     +--ro interface-ref
         |  |        +--ro state
         |  |           +--ro interface?      -> /oc-if:interfaces/interface/name
         |  |           +--ro subinterface?   -> /oc-if:interfaces/interface[oc-if:name=current()/../interface]/subinterfaces/subinterface/index
         |  +--ro oc-aft-counters:counters
         |  |  +--ro oc-aft-counters:ipv4-unicast
         |  |  |  +--ro oc-aft-counters:ipv4-entry* [prefix]
         |  |  |     +--ro oc-aft-counters:prefix    -> ../state/prefix
         |  |  |     +--ro oc-aft-counters:state
         |  |  |        +--ro oc-aft-counters:prefix?                     oc-inet:ipv4-prefix
         |  |  |        +--ro oc-aft-counters:packets-forwarded?          oc-yang:counter64
         |  |  |        +--ro oc-aft-counters:octets-forwarded?           oc-yang:counter64
         |  |  |        +--ro oc-aft-counters:packets-forwarded-backup?   oc-yang:counter64
         |  |  |        +--ro oc-aft-counters:octets-forwarded-backup?    oc-yang:counter64
         |  |  +--ro oc-aft-counters:ipv6-unicast
         |  |  |  +--ro oc-aft-counters:ipv6-entry* [prefix]
         |  |  |     +--ro oc-aft-counters:prefix    -> ../state/prefix
         |  |  |     +--ro oc-aft-counters:state
         |  |  |        +--ro oc-aft-counters:prefix?                     oc-inet:ipv6-prefix
         |  |  |        +--ro oc-aft-counters:packets-forwarded?          oc-yang:counter64
         |  |  |        +--ro oc-aft-counters:octets-forwarded?           oc-yang:counter64
         |  |  |        +--ro oc-aft-counters:packets-forwarded-backup?   oc-yang:counter64
         |  |  |        +--ro oc-aft-counters:octets-forwarded-backup?    oc-yang:counter64
         |  |  +--ro oc-aft-counters:mpls
         |  |  |  +--ro oc-aft-counters:label-entry* [label]
         |  |  |     +--ro oc-aft-counters:label    -> ../state/label
         |  |  |     +--ro oc-aft-counters:state
         |  |  |        +--ro oc-aft-counters:label?               oc-mplst:mpls-label
         |  |  |        +--ro oc-aft-counters:packets-forwarded?   oc-yang:counter64
         |  |  |        +--ro oc-aft-counters:octets-forwarded?    oc-yang:counter64
+        |  |  +--ro oc-aft-counters:ipv4-multicast
+        |  |  |  +--ro oc-aft-counters:ipv4-multicast-entry* [source-address group-address]
+        |  |  |     +--ro oc-aft-counters:source-address    -> ../state/source-address
+        |  |  |     +--ro oc-aft-counters:group-address     -> ../state/group-address
+        |  |  |     +--ro oc-aft-counters:state
+        |  |  |        +--ro oc-aft-counters:source-address?      oc-inet:ipv4-address
+        |  |  |        +--ro oc-aft-counters:group-address?       oc-inet:ipv4-address
+        |  |  |        +--ro oc-aft-counters:packets-forwarded?   oc-yang:counter64
+        |  |  |        +--ro oc-aft-counters:octets-forwarded?    oc-yang:counter64
+        |  |  |        +--ro oc-aft-counters:rpf-discards?        oc-yang:counter64
+        |  |  +--ro oc-aft-counters:ipv6-multicast
+        |  |  |  +--ro oc-aft-counters:ipv6-multicast-entry* [source-address group-address]
+        |  |  |     +--ro oc-aft-counters:source-address    -> ../state/source-address
+        |  |  |     +--ro oc-aft-counters:group-address     -> ../state/group-address
+        |  |  |     +--ro oc-aft-counters:state
+        |  |  |        +--ro oc-aft-counters:source-address?      oc-inet:ipv6-address
+        |  |  |        +--ro oc-aft-counters:group-address?       oc-inet:ipv6-address
+        |  |  |        +--ro oc-aft-counters:packets-forwarded?   oc-yang:counter64
+        |  |  |        +--ro oc-aft-counters:octets-forwarded?    oc-yang:counter64
+        |  |  |        +--ro oc-aft-counters:rpf-discards?        oc-yang:counter64
+        |  |  +--ro oc-aft-counters:mpls-multicast
+        |  |  |  +--ro oc-aft-counters:multicast-label-entry* [label]
+        |  |  |     +--ro oc-aft-counters:label    -> ../state/label
+        |  |  |     +--ro oc-aft-counters:state
+        |  |  |        +--ro oc-aft-counters:label?               oc-mplst:mpls-label
+        |  |  |        +--ro oc-aft-counters:packets-forwarded?   oc-yang:counter64
+        |  |  |        +--ro oc-aft-counters:octets-forwarded?    oc-yang:counter64
         |  |  +--ro oc-aft-counters:ethernet
         |  |  |  +--ro oc-aft-counters:mac-entry* [mac-address]
         |  |  |     +--ro oc-aft-counters:mac-address    -> ../state/mac-address
         |  |  |     +--ro oc-aft-counters:state
         |  |  |        +--ro oc-aft-counters:mac-address?         oc-yang:mac-address
         |  |  |        +--ro oc-aft-counters:packets-forwarded?   oc-yang:counter64
         |  |  |        +--ro oc-aft-counters:octets-forwarded?    oc-yang:counter64
         |  |  +--ro oc-aft-counters:policy-forwarding
         |  |  |  +--ro oc-aft-counters:policy-forwarding-entry* [index]
         |  |  |     +--ro oc-aft-counters:index    -> ../state/index
         |  |  |     +--ro oc-aft-counters:state
         |  |  |        +--ro oc-aft-counters:index?               uint64
         |  |  |        +--ro oc-aft-counters:packets-forwarded?   oc-yang:counter64
         |  |  |        +--ro oc-aft-counters:octets-forwarded?    oc-yang:counter64
         |  |  +--ro oc-aft-counters:next-hops
         |  |     +--ro oc-aft-counters:next-hop* [index]
         |  |        +--ro oc-aft-counters:index    -> ../state/index
         |  |        +--ro oc-aft-counters:state
         |  |           +--ro oc-aft-counters:index?               uint64
         |  |           +--ro oc-aft-counters:packets-forwarded?   oc-yang:counter64
         |  |           +--ro oc-aft-counters:octets-forwarded?    oc-yang:counter64
         |  +--rw oc-aft-gf:global-filter
         |  |  +--rw oc-aft-gf:config
         |  |  |  +--rw oc-aft-gf:ipv6-policy?   -> /oc-rpol:routing-policy/policy-definitions/policy-definition/config/name
         |  |  |  +--rw oc-aft-gf:ipv4-policy?   -> /oc-rpol:routing-policy/policy-definitions/policy-definition/config/name
         |  |  +--ro oc-aft-gf:state
         |  |     +--ro oc-aft-gf:ipv6-policy?   -> /oc-rpol:routing-policy/policy-definitions/policy-definition/config/name
         |  |     +--ro oc-aft-gf:ipv4-policy?   -> /oc-rpol:routing-policy/policy-definitions/policy-definition/config/name
         |  +--rw oc-aftsummary:aft-summaries
         |     +--rw oc-aftsummary:ipv4-unicast
         |     |  +--ro oc-aftsummary:protocols
         |     |     +--ro oc-aftsummary:protocol* [origin-protocol]
         |     |        +--ro oc-aftsummary:origin-protocol    -> ../state/origin-protocol
         |     |        +--ro oc-aftsummary:state
         |     |           +--ro oc-aftsummary:origin-protocol?   identityref
         |     |           +--ro oc-aftsummary:counters
         |     |              +--ro oc-aftsummary:aft-entries?   uint64
         |     +--rw oc-aftsummary:ipv6-unicast
         |        +--ro oc-aftsummary:protocols
         |           +--ro oc-aftsummary:protocol* [origin-protocol]
         |              +--ro oc-aftsummary:origin-protocol    -> ../state/origin-protocol
         |              +--ro oc-aftsummary:state
         |                 +--ro oc-aftsummary:origin-protocol?   identityref
         |                 +--ro oc-aftsummary:counters
         |                    +--ro oc-aftsummary:aft-entries?   uint64
         +--rw protocols
         |  +--rw protocol* [identifier name]
         |     +--rw identifier          -> ../config/identifier
         |     +--rw name                -> ../config/name
         |     +--rw config
         |     |  +--rw identifier?       identityref
         |     |  +--rw name?             string
         |     |  +--rw enabled?          boolean
         |     |  +--rw default-metric?   uint32
         |     +--ro state
         |     |  +--ro identifier?       identityref
         |     |  +--ro name?             string
         |     |  +--ro enabled?          boolean
         |     |  +--ro default-metric?   uint32
         |     +--rw static-routes
         |     |  +--rw static* [prefix]
         |     |     +--rw prefix                              -> ../config/prefix
         |     |     +--rw config
         |     |     |  +--rw prefix?        inet:ip-prefix
         |     |     |  +--rw set-tag?       oc-pt:tag-type
         |     |     |  +--rw description?   string
         |     |     +--ro state
         |     |     |  +--ro prefix?        inet:ip-prefix
         |     |     |  +--ro set-tag?       oc-pt:tag-type
         |     |     |  +--ro description?   string
         |     |     +--rw next-hops
         |     |     |  +--rw next-hop* [index]
         |     |     |     +--rw index            -> ../config/index
         |     |     |     +--rw config
         |     |     |     |  +--rw index?                                     string
         |     |     |     |  +--rw next-hop?                                  union
         |     |     |     |  +--rw recurse?                                   boolean
         |     |     |     |  +--rw metric?                                    uint32
         |     |     |     |  +--rw preference?                                uint32
         |     |     |     |  +--rw wecmp-weight?                              union
         |     |     |     |  +--rw oc-loc-rt-netinst:next-network-instance?   -> /oc-ni:network-instances/network-instance/config/name
         |     |     |     |  +--rw oc-loc-rt-netinst:nh-network-instance?     -> /oc-ni:network-instances/network-instance/config/name
         |     |     |     +--ro state
         |     |     |     |  +--ro index?                                     string
         |     |     |     |  +--ro next-hop?                                  union
         |     |     |     |  +--ro recurse?                                   boolean
         |     |     |     |  +--ro metric?                                    uint32
         |     |     |     |  +--ro preference?                                uint32
         |     |     |     |  +--ro wecmp-weight?                              union
         |     |     |     |  +--ro oc-loc-rt-netinst:next-network-instance?   -> /oc-ni:network-instances/network-instance/config/name
         |     |     |     |  +--ro oc-loc-rt-netinst:nh-network-instance?     -> /oc-ni:network-instances/network-instance/config/name
         |     |     |     +--rw enable-bfd
         |     |     |     |  +--rw config
         |     |     |     |  |  +--rw enabled?                       boolean
         |     |     |     |  |  +--rw desired-minimum-tx-interval?   uint32
         |     |     |     |  |  +--rw required-minimum-receive?      uint32
         |     |     |     |  |  +--rw detection-multiplier?          uint8
         |     |     |     |  +--ro state
         |     |     |     |     +--ro enabled?                       boolean
         |     |     |     |     +--ro desired-minimum-tx-interval?   uint32

@bewing bewing requested a review from a team as a code owner April 2, 2026 21:24
@bewing

bewing commented Apr 2, 2026

Copy link
Copy Markdown
Contributor Author

FWIW, I swear I had opened a similar PR/ticket back in 2018....ish, but I can't find it now.

edit: found it

#197

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for multicast forwarding tables (AFT) within the OpenConfig model, specifically adding submodules for IPv4, IPv6, and MPLS P2MP multicast forwarding. It defines new groupings for multicast outgoing interface states and structural lists, which are integrated into the main AFT module. Review feedback recommends utilizing existing common groupings in the new IPv4 and IPv6 submodules to ensure consistency and minimize code duplication.

Comment thread release/models/aft/openconfig-aft-ipv4-multicast.yang Outdated
Comment thread release/models/aft/openconfig-aft-ipv6-multicast.yang Outdated
@dplore dplore moved this to Ready to discuss in OC Operator Review Apr 3, 2026
Comment thread release/models/aft/openconfig-aft-ipv4-multicast.yang Outdated
@bewing bewing force-pushed the feat/mft branch 2 times, most recently from d5ccef2 to fd48ac6 Compare May 5, 2026 14:51
@bewing

bewing commented May 5, 2026

Copy link
Copy Markdown
Contributor Author

Pushed a new changeset based on feedback received.

Using the existing NHG pattern has the side effect of removing RPF information from the model. This is important information to have (traffic received on the non-RPF interface isn't forwarded, usually punted to CPU/control plane). Where is the right place to put this information? Should it just be a leaf in the mc-entry/state grouping? Somewhere in the AFT-common tree?

@bewing bewing requested a review from akalluru1 May 5, 2026 14:57
@bewing

bewing commented May 5, 2026

Copy link
Copy Markdown
Contributor Author

Just noticed I need to incorporate some recent changes in the MPLS modeling into this change, working on that now.

@bewing

bewing commented May 5, 2026

Copy link
Copy Markdown
Contributor Author

Additional question - unicast MPLS AFT doesn't include aft-common-install-protocol in grouping aft-mpls-entry-state - is this an oversight in that AFT? oc-mpls:signaling-protocols seems like the likely reference here.

@bewing bewing force-pushed the feat/mft branch 2 times, most recently from 632029b to 50c70f7 Compare May 5, 2026 16:22

@akalluru1 akalluru1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some preliminary comments below, I'll review the changes one more time to thoroughly look at the description & few other things.

Comment thread release/models/aft/openconfig-aft-ipv4-multicast.yang Outdated
Comment thread release/models/aft/openconfig-aft-ipv6-multicast.yang Outdated
@bewing

bewing commented May 20, 2026

Copy link
Copy Markdown
Contributor Author

Using the existing NHG pattern has the side effect of removing RPF information from the model. This is important information to have (traffic received on the non-RPF interface isn't forwarded, usually punted to CPU/control plane). Where is the right place to put this information? Should it just be a leaf in the mc-entry/state grouping? Somewhere in the AFT-common tree?

For now, I have added an interface ref to the state container for IPv4 and IPv6

@dplore

dplore commented May 26, 2026

Copy link
Copy Markdown
Member

/gcbrun

@OpenConfigBot

Copy link
Copy Markdown

No major YANG version changes in commit 0da7f87

@dplore

dplore commented May 26, 2026

Copy link
Copy Markdown
Member

@rgwilton @earies @jsterne for review

@dplore

dplore commented May 26, 2026

Copy link
Copy Markdown
Member

Adding to June OC Community review for visibility

@earies

earies commented May 26, 2026

Copy link
Copy Markdown
Contributor

@rgwilton @earies @jsterne for review

checking on this and will revert back

@nsr-gh

nsr-gh commented Jun 20, 2026

Copy link
Copy Markdown

Can you clarify which fields/leafs in a Next-Hop Group (NHG) and Next-Hop (NH) are relevant/applicable when a multicast route uses an NHG/NH?
As per the current model, an NHG uses multiple NHs in cases like ECMP, where traffic is distributed across the various legs of the NHG based on weight. In the case of multicast, however, all packets are sent to all legs. How will this behavior be represented using the existing NHG/NH model?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Ready to discuss

Development

Successfully merging this pull request may close these issues.

7 participants