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
Copy link
Copy Markdown
Contributor

@bewing bewing commented Apr 2, 2026

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-05 09:50:50.188072742 -0500
+++ /home/bewing/new-tree.txt   2026-05-05 11:21:49.942691210 -0500
@@ -3829,200 +3829,252 @@
         |  |        +--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 rpf-discards?                               oc-yang:counter64
+        |  |        +--ro reverse-path-neighbor?                      oc-inet:ipv4-address
+        |  |        +--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 rpf-discards?                               oc-yang:counter64
+        |  |        +--ro reverse-path-neighbor?                      oc-inet:ipv6-address
+        |  |        +--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

@bewing bewing requested a review from a team as a code owner April 2, 2026 21:24
@bewing
Copy link
Copy Markdown
Contributor Author

bewing commented Apr 2, 2026

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

Copy link
Copy Markdown
Contributor

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

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
Copy link
Copy Markdown
Contributor Author

bewing commented May 5, 2026

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
Copy link
Copy Markdown
Contributor Author

bewing commented May 5, 2026

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

@bewing
Copy link
Copy Markdown
Contributor Author

bewing commented May 5, 2026

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.

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

Labels

None yet

Projects

Status: Ready to discuss

Development

Successfully merging this pull request may close these issues.

4 participants