Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support to configure interface virtual gateway #927

Closed
wants to merge 0 commits into from

Conversation

vsrx
Copy link

@vsrx vsrx commented Jul 26, 2023

Change Scope

  • Similar to the VRRP protocol, vendors allow to configure a virtual address on interfaces to forward traffic in an active-active configuration as opposed to active-standby modes with VRRP.
  • This change is backward compatible.

Platform Implementations

Arista:

ip virtual-router mac-address 00:00:5e:00:00:01
interface Vlan10
  ip address virtual 10.1.1.254/24
  mac address virtual-router

Juniper:

interfaces {
    irb {
        unit 1 {
            family inet {
                address 10.1.1.1/24 {
                    virtual-gateway-address 10.1.1.254;
                }
            }
            mac 00:00:5e:00:00:01;
        }
}

@vsrx vsrx requested a review from a team as a code owner July 26, 2023 14:58
@vsrx
Copy link
Author

vsrx commented Jul 26, 2023

fixes #919

@OpenConfigBot
Copy link

OpenConfigBot commented Jul 26, 2023

Major YANG version changes in commit f704e13:

@vsrx
Copy link
Author

vsrx commented Jul 26, 2023

Visualized YANG tree after change:

(pyang) [LOAS] vsrx@oxygen:~/yang_modules$ pyang -f tree openconfig-if-ip.yang 
module: openconfig-if-ip

  augment /oc-if:interfaces/oc-if:interface/oc-if:subinterfaces/oc-if:subinterface:
    +--rw ipv4
       +--rw addresses
       |  +--rw address* [ip]
       |     +--rw ip                 -> ../config/ip
       |     +--rw config
       |     |  +--rw ip?              oc-inet:ipv4-address
       |     |  +--rw prefix-length?   uint8
       |     |  +--rw type?            ipv4-address-type
       |     +--ro state
       |     |  +--ro ip?              oc-inet:ipv4-address
       |     |  +--ro prefix-length?   uint8
       |     |  +--ro type?            ipv4-address-type
       |     |  +--ro origin?          ip-address-origin
       |     +--rw vrrp
       |     |  +--rw vrrp-group* [virtual-router-id]
       |     |     +--rw virtual-router-id     -> ../config/virtual-router-id
       |     |     +--rw config
       |     |     |  +--rw virtual-router-id?        uint8
       |     |     |  +--rw virtual-address*          oc-inet:ip-address
       |     |     |  +--rw priority?                 uint8
       |     |     |  +--rw preempt?                  boolean
       |     |     |  +--rw preempt-delay?            uint16
       |     |     |  +--rw accept-mode?              boolean
       |     |     |  +--rw advertisement-interval?   uint16
       |     |     +--ro state
       |     |     |  +--ro virtual-router-id?        uint8
       |     |     |  +--ro virtual-address*          oc-inet:ip-address
       |     |     |  +--ro priority?                 uint8
       |     |     |  +--ro preempt?                  boolean
       |     |     |  +--ro preempt-delay?            uint16
       |     |     |  +--ro accept-mode?              boolean
       |     |     |  +--ro advertisement-interval?   uint16
       |     |     |  +--ro current-priority?         uint8
       |     |     +--rw interface-tracking
       |     |        +--rw config
       |     |        |  +--rw track-interface*      -> /oc-if:interfaces/interface/name
       |     |        |  +--rw priority-decrement?   uint8
       |     |        +--ro state
       |     |           +--ro track-interface*      -> /oc-if:interfaces/interface/name
       |     |           +--ro priority-decrement?   uint8
       |     +--rw virtual-gateway
       |        +--rw config
       |        |  +--rw virtual-address?   oc-inet:ip-address
       |        +--ro state
       |           +--ro virtual-address?   oc-inet:ip-address
       +--rw proxy-arp
       |  +--rw config
       |  |  +--rw mode?   enumeration
       |  +--ro state
       |     +--ro mode?   enumeration
       +--rw neighbors
       |  +--rw neighbor* [ip]
       |     +--rw ip        -> ../config/ip
       |     +--rw config
       |     |  +--rw ip?                   oc-inet:ipv4-address
       |     |  +--rw link-layer-address    oc-yang:phys-address
       |     +--ro state
       |        +--ro ip?                   oc-inet:ipv4-address
       |        +--ro link-layer-address    oc-yang:phys-address
       |        +--ro origin?               neighbor-origin
       +--rw unnumbered
       |  +--rw config
       |  |  +--rw enabled?   boolean
       |  +--ro state
       |  |  +--ro enabled?   boolean
       |  +--rw interface-ref
       |     +--rw config
       |     |  +--rw interface?      -> /oc-if:interfaces/interface/name
       |     |  +--rw subinterface?   -> /oc-if:interfaces/interface[oc-if:name=current()/../interface]/subinterfaces/subinterface/index
       |     +--ro state
       |        +--ro interface?      -> /oc-if:interfaces/interface/name
       |        +--ro subinterface?   -> /oc-if:interfaces/interface[oc-if:name=current()/../interface]/subinterfaces/subinterface/index
       +--rw config
       |  +--rw enabled?       boolean
       |  +--rw mtu?           uint16
       |  +--rw dhcp-client?   boolean
       +--ro state
          +--ro enabled?       boolean
          +--ro mtu?           uint16
          +--ro dhcp-client?   boolean
          +--ro counters
             +--ro in-forwarded-pkts?      oc-yang:counter64
             +--ro in-forwarded-octets?    oc-yang:counter64
             +--ro out-forwarded-pkts?     oc-yang:counter64
             +--ro out-forwarded-octets?   oc-yang:counter64
  augment /oc-if:interfaces/oc-if:interface/oc-if:subinterfaces/oc-if:subinterface:
    +--rw ipv6
       +--rw addresses
       |  +--rw address* [ip]
       |     +--rw ip                 -> ../config/ip
       |     +--rw config
       |     |  +--rw ip?              oc-inet:ipv6-address
       |     |  +--rw prefix-length    uint8
       |     |  +--rw type?            oc-inet:ipv6-address-type
       |     +--ro state
       |     |  +--ro ip?              oc-inet:ipv6-address
       |     |  +--ro prefix-length    uint8
       |     |  +--ro type?            oc-inet:ipv6-address-type
       |     |  +--ro origin?          ip-address-origin
       |     |  +--ro status?          enumeration
       |     +--rw vrrp
       |     |  +--rw vrrp-group* [virtual-router-id]
       |     |     +--rw virtual-router-id     -> ../config/virtual-router-id
       |     |     +--rw config
       |     |     |  +--rw virtual-router-id?        uint8
       |     |     |  +--rw virtual-address*          oc-inet:ip-address
       |     |     |  +--rw priority?                 uint8
       |     |     |  +--rw preempt?                  boolean
       |     |     |  +--rw preempt-delay?            uint16
       |     |     |  +--rw accept-mode?              boolean
       |     |     |  +--rw advertisement-interval?   uint16
       |     |     |  +--rw virtual-link-local?       oc-inet:ip-address
       |     |     +--ro state
       |     |     |  +--ro virtual-router-id?        uint8
       |     |     |  +--ro virtual-address*          oc-inet:ip-address
       |     |     |  +--ro priority?                 uint8
       |     |     |  +--ro preempt?                  boolean
       |     |     |  +--ro preempt-delay?            uint16
       |     |     |  +--ro accept-mode?              boolean
       |     |     |  +--ro advertisement-interval?   uint16
       |     |     |  +--ro current-priority?         uint8
       |     |     |  +--ro virtual-link-local?       oc-inet:ip-address
       |     |     +--rw interface-tracking
       |     |        +--rw config
       |     |        |  +--rw track-interface*      -> /oc-if:interfaces/interface/name
       |     |        |  +--rw priority-decrement?   uint8
       |     |        +--ro state
       |     |           +--ro track-interface*      -> /oc-if:interfaces/interface/name
       |     |           +--ro priority-decrement?   uint8
       |     +--rw virtual-gateway
       |        +--rw config
       |        |  +--rw virtual-address?   oc-inet:ipv6-address
       |        +--ro state
       |           +--ro virtual-address?   oc-inet:ipv6-address
       +--rw router-advertisement
       |  +--rw config
       |  |  +--rw enable?         boolean
       |  |  +--rw interval?       uint32
       |  |  +--rw lifetime?       uint32
       |  |  x--rw suppress?       boolean
       |  |  +--rw mode?           enumeration
       |  |  +--rw managed?        boolean
       |  |  +--rw other-config?   boolean
       |  +--ro state
       |  |  +--ro enable?         boolean
       |  |  +--ro interval?       uint32
       |  |  +--ro lifetime?       uint32
       |  |  x--ro suppress?       boolean
       |  |  +--ro mode?           enumeration
       |  |  +--ro managed?        boolean
       |  |  +--ro other-config?   boolean
       |  +--rw prefixes
       |     +--rw prefix* [prefix]
       |        +--rw prefix    -> ../config/prefix
       |        +--rw config
       |        |  +--rw prefix?                      oc-inet:ipv6-prefix
       |        |  +--rw valid-lifetime?              uint32
       |        |  +--rw preferred-lifetime?          uint32
       |        |  +--rw disable-advertisement?       boolean
       |        |  +--rw disable-autoconfiguration?   boolean
       |        |  +--rw enable-onlink?               boolean
       |        +--ro state
       |           +--ro prefix?                      oc-inet:ipv6-prefix
       |           +--ro valid-lifetime?              uint32
       |           +--ro preferred-lifetime?          uint32
       |           +--ro disable-advertisement?       boolean
       |           +--ro disable-autoconfiguration?   boolean
       |           +--ro enable-onlink?               boolean
       +--rw neighbors
       |  +--rw neighbor* [ip]
       |     +--rw ip        -> ../config/ip
       |     +--rw config
       |     |  +--rw ip?                   oc-inet:ipv6-address
       |     |  +--rw link-layer-address    oc-yang:phys-address
       |     +--ro state
       |        +--ro ip?                   oc-inet:ipv6-address
       |        +--ro link-layer-address    oc-yang:phys-address
       |        +--ro origin?               neighbor-origin
       |        +--ro is-router?            boolean
       |        +--ro neighbor-state?       enumeration
       +--rw unnumbered
       |  +--rw config
       |  |  +--rw enabled?   boolean
       |  +--ro state
       |  |  +--ro enabled?   boolean
       |  +--rw interface-ref
       |     +--rw config
       |     |  +--rw interface?      -> /oc-if:interfaces/interface/name
       |     |  +--rw subinterface?   -> /oc-if:interfaces/interface[oc-if:name=current()/../interface]/subinterfaces/subinterface/index
       |     +--ro state
       |        +--ro interface?      -> /oc-if:interfaces/interface/name
       |        +--ro subinterface?   -> /oc-if:interfaces/interface[oc-if:name=current()/../interface]/subinterfaces/subinterface/index
       +--rw config
       |  +--rw enabled?                     boolean
       |  +--rw mtu?                         uint32
       |  +--rw dup-addr-detect-transmits?   uint32
       |  +--rw dhcp-client?                 boolean
       +--ro state
          +--ro enabled?                     boolean
          +--ro mtu?                         uint32
          +--ro dup-addr-detect-transmits?   uint32
          +--ro dhcp-client?                 boolean
          +--ro counters
             +--ro in-forwarded-pkts?      oc-yang:counter64
             +--ro in-forwarded-octets?    oc-yang:counter64
             +--ro out-forwarded-pkts?     oc-yang:counter64
             +--ro out-forwarded-octets?   oc-yang:counter64
  augment /oc-if:interfaces/oc-if:interface/oc-vlan:routed-vlan:
    +--rw ipv4
       +--rw addresses
       |  +--rw address* [ip]
       |     +--rw ip                 -> ../config/ip
       |     +--rw config
       |     |  +--rw ip?              oc-inet:ipv4-address
       |     |  +--rw prefix-length?   uint8
       |     |  +--rw type?            ipv4-address-type
       |     +--ro state
       |     |  +--ro ip?              oc-inet:ipv4-address
       |     |  +--ro prefix-length?   uint8
       |     |  +--ro type?            ipv4-address-type
       |     |  +--ro origin?          ip-address-origin
       |     +--rw vrrp
       |     |  +--rw vrrp-group* [virtual-router-id]
       |     |     +--rw virtual-router-id     -> ../config/virtual-router-id
       |     |     +--rw config
       |     |     |  +--rw virtual-router-id?        uint8
       |     |     |  +--rw virtual-address*          oc-inet:ip-address
       |     |     |  +--rw priority?                 uint8
       |     |     |  +--rw preempt?                  boolean
       |     |     |  +--rw preempt-delay?            uint16
       |     |     |  +--rw accept-mode?              boolean
       |     |     |  +--rw advertisement-interval?   uint16
       |     |     +--ro state
       |     |     |  +--ro virtual-router-id?        uint8
       |     |     |  +--ro virtual-address*          oc-inet:ip-address
       |     |     |  +--ro priority?                 uint8
       |     |     |  +--ro preempt?                  boolean
       |     |     |  +--ro preempt-delay?            uint16
       |     |     |  +--ro accept-mode?              boolean
       |     |     |  +--ro advertisement-interval?   uint16
       |     |     |  +--ro current-priority?         uint8
       |     |     +--rw interface-tracking
       |     |        +--rw config
       |     |        |  +--rw track-interface*      -> /oc-if:interfaces/interface/name
       |     |        |  +--rw priority-decrement?   uint8
       |     |        +--ro state
       |     |           +--ro track-interface*      -> /oc-if:interfaces/interface/name
       |     |           +--ro priority-decrement?   uint8
       |     +--rw virtual-gateway
       |        +--rw config
       |        |  +--rw virtual-address?   oc-inet:ip-address
       |        +--ro state
       |           +--ro virtual-address?   oc-inet:ip-address
       +--rw proxy-arp
       |  +--rw config
       |  |  +--rw mode?   enumeration
       |  +--ro state
       |     +--ro mode?   enumeration
       +--rw neighbors
       |  +--rw neighbor* [ip]
       |     +--rw ip        -> ../config/ip
       |     +--rw config
       |     |  +--rw ip?                   oc-inet:ipv4-address
       |     |  +--rw link-layer-address    oc-yang:phys-address
       |     +--ro state
       |        +--ro ip?                   oc-inet:ipv4-address
       |        +--ro link-layer-address    oc-yang:phys-address
       |        +--ro origin?               neighbor-origin
       +--rw unnumbered
       |  +--rw config
       |  |  +--rw enabled?   boolean
       |  +--ro state
       |  |  +--ro enabled?   boolean
       |  +--rw interface-ref
       |     +--rw config
       |     |  +--rw interface?      -> /oc-if:interfaces/interface/name
       |     |  +--rw subinterface?   -> /oc-if:interfaces/interface[oc-if:name=current()/../interface]/subinterfaces/subinterface/index
       |     +--ro state
       |        +--ro interface?      -> /oc-if:interfaces/interface/name
       |        +--ro subinterface?   -> /oc-if:interfaces/interface[oc-if:name=current()/../interface]/subinterfaces/subinterface/index
       +--rw config
       |  +--rw enabled?       boolean
       |  +--rw mtu?           uint16
       |  +--rw dhcp-client?   boolean
       +--ro state
          +--ro enabled?       boolean
          +--ro mtu?           uint16
          +--ro dhcp-client?   boolean
          +--ro counters
             +--ro in-forwarded-pkts?      oc-yang:counter64
             +--ro in-forwarded-octets?    oc-yang:counter64
             +--ro out-forwarded-pkts?     oc-yang:counter64
             +--ro out-forwarded-octets?   oc-yang:counter64
  augment /oc-if:interfaces/oc-if:interface/oc-vlan:routed-vlan:
    +--rw ipv6
       +--rw addresses
       |  +--rw address* [ip]
       |     +--rw ip                 -> ../config/ip
       |     +--rw config
       |     |  +--rw ip?              oc-inet:ipv6-address
       |     |  +--rw prefix-length    uint8
       |     |  +--rw type?            oc-inet:ipv6-address-type
       |     +--ro state
       |     |  +--ro ip?              oc-inet:ipv6-address
       |     |  +--ro prefix-length    uint8
       |     |  +--ro type?            oc-inet:ipv6-address-type
       |     |  +--ro origin?          ip-address-origin
       |     |  +--ro status?          enumeration
       |     +--rw vrrp
       |     |  +--rw vrrp-group* [virtual-router-id]
       |     |     +--rw virtual-router-id     -> ../config/virtual-router-id
       |     |     +--rw config
       |     |     |  +--rw virtual-router-id?        uint8
       |     |     |  +--rw virtual-address*          oc-inet:ip-address
       |     |     |  +--rw priority?                 uint8
       |     |     |  +--rw preempt?                  boolean
       |     |     |  +--rw preempt-delay?            uint16
       |     |     |  +--rw accept-mode?              boolean
       |     |     |  +--rw advertisement-interval?   uint16
       |     |     |  +--rw virtual-link-local?       oc-inet:ip-address
       |     |     +--ro state
       |     |     |  +--ro virtual-router-id?        uint8
       |     |     |  +--ro virtual-address*          oc-inet:ip-address
       |     |     |  +--ro priority?                 uint8
       |     |     |  +--ro preempt?                  boolean
       |     |     |  +--ro preempt-delay?            uint16
       |     |     |  +--ro accept-mode?              boolean
       |     |     |  +--ro advertisement-interval?   uint16
       |     |     |  +--ro current-priority?         uint8
       |     |     |  +--ro virtual-link-local?       oc-inet:ip-address
       |     |     +--rw interface-tracking
       |     |        +--rw config
       |     |        |  +--rw track-interface*      -> /oc-if:interfaces/interface/name
       |     |        |  +--rw priority-decrement?   uint8
       |     |        +--ro state
       |     |           +--ro track-interface*      -> /oc-if:interfaces/interface/name
       |     |           +--ro priority-decrement?   uint8
       |     +--rw virtual-gateway
       |        +--rw config
       |        |  +--rw virtual-address?   oc-inet:ipv6-address
       |        +--ro state
       |           +--ro virtual-address?   oc-inet:ipv6-address
       +--rw router-advertisement
       |  +--rw config
       |  |  +--rw enable?         boolean
       |  |  +--rw interval?       uint32
       |  |  +--rw lifetime?       uint32
       |  |  x--rw suppress?       boolean
       |  |  +--rw mode?           enumeration
       |  |  +--rw managed?        boolean
       |  |  +--rw other-config?   boolean
       |  +--ro state
       |  |  +--ro enable?         boolean
       |  |  +--ro interval?       uint32
       |  |  +--ro lifetime?       uint32
       |  |  x--ro suppress?       boolean
       |  |  +--ro mode?           enumeration
       |  |  +--ro managed?        boolean
       |  |  +--ro other-config?   boolean
       |  +--rw prefixes
       |     +--rw prefix* [prefix]
       |        +--rw prefix    -> ../config/prefix
       |        +--rw config
       |        |  +--rw prefix?                      oc-inet:ipv6-prefix
       |        |  +--rw valid-lifetime?              uint32
       |        |  +--rw preferred-lifetime?          uint32
       |        |  +--rw disable-advertisement?       boolean
       |        |  +--rw disable-autoconfiguration?   boolean
       |        |  +--rw enable-onlink?               boolean
       |        +--ro state
       |           +--ro prefix?                      oc-inet:ipv6-prefix
       |           +--ro valid-lifetime?              uint32
       |           +--ro preferred-lifetime?          uint32
       |           +--ro disable-advertisement?       boolean
       |           +--ro disable-autoconfiguration?   boolean
       |           +--ro enable-onlink?               boolean
       +--rw neighbors
       |  +--rw neighbor* [ip]
       |     +--rw ip        -> ../config/ip
       |     +--rw config
       |     |  +--rw ip?                   oc-inet:ipv6-address
       |     |  +--rw link-layer-address    oc-yang:phys-address
       |     +--ro state
       |        +--ro ip?                   oc-inet:ipv6-address
       |        +--ro link-layer-address    oc-yang:phys-address
       |        +--ro origin?               neighbor-origin
       |        +--ro is-router?            boolean
       |        +--ro neighbor-state?       enumeration
       +--rw unnumbered
       |  +--rw config
       |  |  +--rw enabled?   boolean
       |  +--ro state
       |  |  +--ro enabled?   boolean
       |  +--rw interface-ref
       |     +--rw config
       |     |  +--rw interface?      -> /oc-if:interfaces/interface/name
       |     |  +--rw subinterface?   -> /oc-if:interfaces/interface[oc-if:name=current()/../interface]/subinterfaces/subinterface/index
       |     +--ro state
       |        +--ro interface?      -> /oc-if:interfaces/interface/name
       |        +--ro subinterface?   -> /oc-if:interfaces/interface[oc-if:name=current()/../interface]/subinterfaces/subinterface/index
       +--rw config
       |  +--rw enabled?                     boolean
       |  +--rw mtu?                         uint32
       |  +--rw dup-addr-detect-transmits?   uint32
       |  +--rw dhcp-client?                 boolean
       +--ro state
          +--ro enabled?                     boolean
          +--ro mtu?                         uint32
          +--ro dup-addr-detect-transmits?   uint32
          +--ro dhcp-client?                 boolean
          +--ro counters
             +--ro in-forwarded-pkts?      oc-yang:counter64
             +--ro in-forwarded-octets?    oc-yang:counter64
             +--ro out-forwarded-pkts?     oc-yang:counter64
             +--ro out-forwarded-octets?   oc-yang:counter64

@OpenConfigBot
Copy link

OpenConfigBot commented Jul 26, 2023

Compatibility Report for commit f704e13:
pyangbind@eb2d4a7

@rolandphung
Copy link
Contributor

rolandphung commented Jul 26, 2023

I've always wondered, why does this have to be keyed under an ip address? At least for Arista, the VARP gateway address does not have to be under a physical address's subnet.

@vsrx
Copy link
Author

vsrx commented Jul 26, 2023

Initially I shared the same thought, but I was particularly inclined towards the section in the documentation that mentions, "A virtual IP address may optionally be configured with a subnet." I also followed a similar approach to the implementation of VRRP. However, would be open to hear other suggestions as well.

https://www.arista.com/en/um-eos/eos-varp#xx1156452

@rolandphung
Copy link
Contributor

I was particularly inclined towards the section in the documentation that mentions, "A virtual IP address may optionally be configured with a subnet."

This is an IPv4 only feature:
https://www.arista.com/en/support/toi/eos-4-15-0f/13628-source-arp-with-virtual-ip

@dplore
Copy link
Member

dplore commented Jul 26, 2023

I've always wondered, why does this have to be keyed under an ip address? At least for Arista, the VARP gateway address does not have to be under a physical address's subnet.

In the case of OC, I think it's precedent for this pattern. The OC pattern to configure an IP address related to an interface is to add it to a list under the /interfaces/interface/subinterfaces/subinterface/ipv[4,6]/addresses/address

Other structures are possible but unless they have a functional difference that is not easily met using the existing pattern, then the existing pattern is preferred. Do you have a suggestion for another list or container to add the virtual-gateway IP addresses?

@vsrx Is it helpful to specify which mac address should be used for the virtual gateway IP address? Do you need to include an option to configure the mac address too? Both referenced implementations have this as an option.

@vsrx
Copy link
Author

vsrx commented Jul 26, 2023

I was particularly inclined towards the section in the documentation that mentions, "A virtual IP address may optionally be configured with a subnet."

This is an IPv4 only feature: https://www.arista.com/en/support/toi/eos-4-15-0f/13628-source-arp-with-virtual-ip

Ah, thank you for the reference. The part where the documentation refers to configuring an IPv6 address - does this mean it gets nested to the prefix as opposed to the interface for IPv4?

switch(config)# interface vlan 10
switch(config-if-Vl10)# ipv6 address 2001:0DB8:0:1::1/64
switch(config-if-Vl10)# ipv6 virtual-router address 2001:0DB8:0:1::2
switch(config-if-Vl10)# exit

@rolandphung
Copy link
Contributor

Ah, thank you for the reference. The part where the documentation refers to configuring an IPv6 address - does this mean it gets nested to the prefix as opposed to the interface for IPv4?

No, the feature is only supported on IPv4 so IPv6 there would be no subnets available. So in general, a virtual IP with no subnet is just a host IP. e.g. ipv6 virtual-router address 2001:0DB8:0:1::2 would have a "subnet" of /128 and a IPv4 configuration ip virtual-router address 10.1.1.254 would have a subnet of /32

@rolandphung
Copy link
Contributor

rolandphung commented Jul 26, 2023

@vsrx Is it helpful to specify which mac address should be used for the virtual gateway IP address? Do you need to include an option to configure the mac address too? Both referenced implementations have this as an option.

Currently we baked the virtual gateway mac address into /system/mac-address/config/routing-mac.

@vsrx
Copy link
Author

vsrx commented Jul 26, 2023

I've always wondered, why does this have to be keyed under an ip address? At least for Arista, the VARP gateway address does not have to be under a physical address's subnet.

In the case of OC, I think it's precedent for this pattern. The OC pattern to configure an IP address related to an interface is to add it to a list under the /interfaces/interface/subinterfaces/subinterface/ipv[4,6]/addresses/address

Other structures are possible but unless they have a functional difference that is not easily met using the existing pattern, then the existing pattern is preferred. Do you have a suggestion for another list or container to add the virtual-gateway IP addresses?

@vsrx Is it helpful to specify which mac address should be used for the virtual gateway IP address? Do you need to include an option to configure the mac address too? Both referenced implementations have this as an option.

Yeah, as per my understanding - Arista only supports a single device level virtual mac address as opposed to interface level ones with Juniper.

There is also a vrf level reference to the anycast-gateway-mac in /network-instances/network-instance/fdb/anycast-gateway-mac

@rolandphung
Copy link
Contributor

rolandphung commented Jul 26, 2023

Other structures are possible but unless they have a functional difference that is not easily met using the existing pattern, then the existing pattern is preferred. Do you have a suggestion for another list or container to add the virtual-gateway IP addresses?

With the proposed structure, it does not fully cover the existing implementation for Arista. VARP supports multiple virtual IP address on one interface and it is less restrictive as in the virtual IP not having to be under the physical subnet. One purpose of this feature being less restrictive is to save on IP address usage.

My personal stance would be to place virtual-gateway container on the ipv4/ipv6 level and have this be a list of addresses. Unfortunately this also isn't very vendor neutral either.

@rochertov
Copy link

Other structures are possible but unless they have a functional difference that is not easily met using the existing pattern, then the existing pattern is preferred. Do you have a suggestion for another list or container to add the virtual-gateway IP addresses?

With the proposed structure, it does not fully cover the existing implementation for Arista. VARP supports multiple virtual IP address on one interface and it is less restrictive as in the virtual IP not having to be under the physical subnet. One purpose of this feature being less restrictive is to save on IP address usage.

In some customer environments that are IPv4 constrained it is imperative to reduce IP address usage.

@vsattri
Copy link

vsattri commented Jul 27, 2023

Other structures are possible but unless they have a functional difference that is not easily met using the existing pattern, then the existing pattern is preferred. Do you have a suggestion for another list or container to add the virtual-gateway IP addresses?

With the proposed structure, it does not fully cover the existing implementation for Arista. VARP supports multiple virtual IP address on one interface and it is less restrictive as in the virtual IP not having to be under the physical subnet. One purpose of this feature being less restrictive is to save on IP address usage.

In some customer environments that are IPv4 constrained it is imperative to reduce IP address usage.

IMO this is pretty close to VRRP feature and should follow similar structure. I understand the concern of IP conservation.

Potentially we could have a compromise:

  1. Have this proposal as is, which lets physical address and virtual address association. Lets you produce:
interfaces {
   irb {
       unit 1 {
           family inet {
               address 10.1.1.1/24 {
                   virtual-gateway-address 10.1.1.254;
               }
           }
       }
}
  1. Plus another knob inside the
   +--rw ipv4
       +--rw addresses
       |  +--rw address* [ip]
       |     +--rw ip                 -> ../config/ip
       |     +--rw config
       |     |  +--rw ip?              oc-inet:ipv4-address
       |     |  +--rw prefix-length?   uint8
       |     |  +--rw type?            ipv4-address-type

and have a bool to say virtual_address or something similar.
Lets you produce:

interface Vlan10
  ip address virtual 10.1.1.1/24
  mac address virtual-mac

@rolandphung how does the flag virtual change the behavior of arista, I assume this lets switch tie ip address to virtual mac.

Is the above tie equivalent of doing (arista doesn't seem to support override of mac or irb/vlan) or is there more to it than that?

interface Vlan10
  ip address  10.1.1.1/24
  mac-address 0000.000a.bbbb

@dplore
Copy link
Member

dplore commented Jul 27, 2023

I do agree that OC should support assigning a virtual-gateway address which is independent of whatever ip/subnet is currently configured. Here is one way which I think is what @vsattri is suggesting:

    +--rw ipv4
       +--rw addresses
       |  +--rw address* [ip]
       |     +--rw ip                 -> ../config/ip
       |     +--rw config
       |     |  +--rw ip?              oc-inet:ipv6-address
       |     |  +--rw prefix-length    uint8
       |     |  +--rw type?            oc-inet:ipv6-address-type
       |     |  +--rw is-virtual-gateway?            boolean  (default to false)

Regarding configuration of the mac address: One idea is OC could define a configuration per virtual IP, even if some implementations only support a single mac. An implementation could require the mac addresses to be the same for IP addresses with virtual-gateway set to true and return an error if different. While this isn't as explicit as having a leaf ref to a single instance of a "routing-mac" as proposed by Roland, it would allow a single model to exist which supports these two different behaviors.

Example model:

    +--rw ipv4
       +--rw addresses
       |  +--rw address* [ip]
       |     +--rw ip                 -> ../config/ip
       |     +--rw config
       |     |  +--rw ip?              oc-inet:ipv6-address
       |     |  +--rw prefix-length    uint8
       |     |  +--rw type?            oc-inet:ipv6-address-type
       |     |  +--rw is-virtual-gateway?            boolean  (default to false)
       |     |  +--rw is-virtual-gateway-mac?           mac-address

I want to avoid having two OC modeled ways to configure the same feature in OC which are mutually exclusive across vendors.

@vsattri
Copy link

vsattri commented Jul 27, 2023

I do agree that OC should support assigning a virtual-gateway address which is independent of whatever ip/subnet is currently configured. Here is one way which I think is what @vsattri is suggesting:

    +--rw ipv4
       +--rw addresses
       |  +--rw address* [ip]
       |     +--rw ip                 -> ../config/ip
       |     +--rw config
       |     |  +--rw ip?              oc-inet:ipv6-address
       |     |  +--rw prefix-length    uint8
       |     |  +--rw type?            oc-inet:ipv6-address-type
       |     |  +--rw is-virtual-gateway?            boolean  (default to false)

Regarding configuration of the mac address: One idea is OC could define a configuration per virtual IP, even if some implementations only support a single mac. An implementation could require the mac addresses to be the same for IP addresses with virtual-gateway set to true and return an error if different. While this isn't as explicit as having a leaf ref to a single instance of a "routing-mac" as proposed by Roland, it would allow a single model to exist which supports these two different behaviors.

Example model:

    +--rw ipv4
       +--rw addresses
       |  +--rw address* [ip]
       |     +--rw ip                 -> ../config/ip
       |     +--rw config
       |     |  +--rw ip?              oc-inet:ipv6-address
       |     |  +--rw prefix-length    uint8
       |     |  +--rw type?            oc-inet:ipv6-address-type
       |     |  +--rw is-virtual-gateway?            boolean  (default to false)
       |     |  +--rw is-virtual-gateway-mac?           mac-address

I want to avoid having two OC modeled ways to configure the same feature in OC which are mutually exclusive across vendors.

Just to visualize what OC would like in 2 cases: Notice proposing changing is-virtual-gateway-mac to has-virtual-gateway-mac. Also Juniper also likes to put virtual mac address itself on the interface so maybe we should make that optional field as well to add mac-address under may be in the interface hierarchy rather than IP hierarchy (possible in a different pull request)?

Arista as is with just virtual address no physical address would look like:

                    "openconfig-if-ip:ipv4": {
                      "addresses": {
                        "address": [
                          {
                            "config": {
                              "ip": "10.1.7.253",
                              "prefix-length": 21
                              "is-virtual-gateway": true
                              "has-virtual-gateway": true
                            },
                          }
                        ]
                      },

Juniper as is with physical + virtual would look like:

                    # physical
                    "openconfig-if-ip:ipv4": {
                      "addresses": {
                        "address": [
                          {
                            "config": {
                              "ip": "10.1.7.0",
                              "prefix-length": 21
                            },
                          }
                        ]
                      },
                    # virtual has no prefix-len on it, i assume that validates, else can be /32?
                    "openconfig-if-ip:ipv4": {
                      "addresses": {
                        "address": [
                          {
                            "config": {
                              "ip": "10.1.7.253",
                              "is-virtual-gateway": true
                              "has-virtual-gateway": true
                            },
                          }
                        ]
                      },

@rolandphung
Copy link
Contributor

and have a bool to say virtual_address or something similar. Lets you produce:

interface Vlan10
  ip address virtual 10.1.1.1/24
  mac address virtual-mac

Small note, ip address virtual is yet another different feature that creates an anycast IP and has a different use case (used to save IP addresses in a VxLAN vtep context)
https://arista.my.site.com/AristaCommunity/s/question/0D52I00007ERMXmSAP/what-is-different-between-ip-virtualrouter-address-and-ip-address-virtual-command

mac address virtual-router functionally changes the interface mac address to the virtual-mac, effectively overriding the source IP/mac address of outgoing packets. This is functionally different than having the virtual IP be used as a gateway.

@rolandphung how does the flag virtual change the behavior of arista, I assume this lets switch tie ip address to virtual mac.

Is the above tie equivalent of doing (arista doesn't seem to support override of mac or irb/vlan) or is there more to it than that?

interface Vlan10
  ip address  10.1.1.1/24
  mac-address 0000.000a.bbbb

This set of configuration is functionally different than the one describe above. I'm not too familiar with the underlying nuances of ip address virtual, but I have confident that it is not going to behave the same as ip virtual-router address

@rolandphung
Copy link
Contributor

Regarding configuration of the mac address: One idea is OC could define a configuration per virtual IP, even if some implementations only support a single mac. An implementation could require the mac addresses to be the same for IP addresses with virtual-gateway set to true and return an error if different. While this isn't as explicit as having a leaf ref to a single instance of a "routing-mac" as proposed by Roland, it would allow a single model to exist which supports these two different behaviors.

With this, it seems like we could go one step further to separate physical IPs from virtual-gateway IPs:

  +--rw interfaces
     +--rw interface* [name]
        +--rw oc-vlan:routed-vlan
           +--rw oc-ip:ipv4
              +--rw oc-ip:virtual-gateway
                 +--rw oc-ip:addresses
                    +--rw oc-ip:address* [ip]
                       +--rw oc-ip:ip        -> ../config/ip
                       +--rw oc-ip:config
                       |  +--rw oc-ip:ip?              oc-inet:ipv4-address
                       |  +--rw oc-ip:prefix-length?   uint8
                       |  +--rw oc-ip:type?            ipv4-address-type
                       +--ro oc-ip:state
                          +--ro oc-ip:ip?              oc-inet:ipv4-address
                          +--ro oc-ip:prefix-length?   uint8
                          +--ro oc-ip:type?            ipv4-address-type

There doesn't seem like there is a need to have the VRRP configuration under the virtual address. (One can also argue that VRRP does not belong below the physical IP address with the way it's currently modeled. I think I'll raise a separate issue to discuss this)

@xandrorel
Copy link

Small note, ip address virtual is yet another different feature that creates an anycast IP and has a different use case (used to save IP addresses in a VxLAN vtep context)
https://arista.my.site.com/AristaCommunity/s/question/0D52I00007ERMXmSAP/what-is-different-between-ip-virtualrouter-address-and-ip-address-virtual-command

Agreed that "ip virtual-router address" and "ip address virtual" are two different features with their own use cases, unfortunately both of these do not fully support our use case. Our use case is quite simple (below is pseudoCLI):

interface vlan10
  ip address 10.1.1.253/24
  ip virtual-gateway address 10.1.1.254/24
  mac virtual-gateway-v4 address 0000.1111.2222

interface should have unique ip address, and can respond with bia or system mac.
interface should have anycast ip address (should allow allocation from the same subnet as interface's unique address)
anycast ip should be associated with virtual mac (either device level or interface level) and send frames with source mac set to this virtual mac.

@vsattri
Copy link

vsattri commented Jul 28, 2023

and have a bool to say virtual_address or something similar. Lets you produce:

interface Vlan10
  ip address virtual 10.1.1.1/24
  mac address virtual-mac

Small note, ip address virtual is yet another different feature that creates an anycast IP and has a different use case (used to save IP addresses in a VxLAN vtep context) https://arista.my.site.com/AristaCommunity/s/question/0D52I00007ERMXmSAP/what-is-different-between-ip-virtualrouter-address-and-ip-address-virtual-command

mac address virtual-router functionally changes the interface mac address to the virtual-mac, effectively overriding the source IP/mac address of outgoing packets. This is functionally different than having the virtual IP be used as a gateway.

@rolandphung how does the flag virtual change the behavior of arista, I assume this lets switch tie ip address to virtual mac.
Is the above tie equivalent of doing (arista doesn't seem to support override of mac or irb/vlan) or is there more to it than that?

interface Vlan10
  ip address  10.1.1.1/24
  mac-address 0000.000a.bbbb

This set of configuration is functionally different than the one describe above. I'm not too familiar with the underlying nuances of ip address virtual, but I have confident that it is not going to behave the same as ip virtual-router address

@vsrx is going to fix the main issue text and scrap off ip virtual-router address . We are primarily interested in case of Arista is ip address virtual feature here along with knob mac address virtual-mac.

@vsrx
Copy link
Author

vsrx commented Jul 28, 2023

and have a bool to say virtual_address or something similar. Lets you produce:

interface Vlan10
  ip address virtual 10.1.1.1/24
  mac address virtual-mac

Small note, ip address virtual is yet another different feature that creates an anycast IP and has a different use case (used to save IP addresses in a VxLAN vtep context) https://arista.my.site.com/AristaCommunity/s/question/0D52I00007ERMXmSAP/what-is-different-between-ip-virtualrouter-address-and-ip-address-virtual-command
mac address virtual-router functionally changes the interface mac address to the virtual-mac, effectively overriding the source IP/mac address of outgoing packets. This is functionally different than having the virtual IP be used as a gateway.

@rolandphung how does the flag virtual change the behavior of arista, I assume this lets switch tie ip address to virtual mac.
Is the above tie equivalent of doing (arista doesn't seem to support override of mac or irb/vlan) or is there more to it than that?

interface Vlan10
  ip address  10.1.1.1/24
  mac-address 0000.000a.bbbb

This set of configuration is functionally different than the one describe above. I'm not too familiar with the underlying nuances of ip address virtual, but I have confident that it is not going to behave the same as ip virtual-router address

@vsrx is going to fix the main issue text and scrap off ip virtual-router address . We are primarily interested in case of Arista is ip address virtual feature here along with knob mac address virtual-mac.

Updated the initial comment. Will send a proposal to visualize the same.

@rolandphung
Copy link
Contributor

@vsrx Can you update the initial documentation link to https://www.arista.com/en/um-eos/eos-vxlan-configuration#xx1234730?

@vsrx
Copy link
Author

vsrx commented Jul 28, 2023

@vsrx Can you update the initial documentation link to https://www.arista.com/en/um-eos/eos-vxlan-configuration#xx1234730?

Updated. Thank you!

@vsrx
Copy link
Author

vsrx commented Aug 3, 2023

@rolandphung Are we good nesting the virtual gateway under the address as per the current proposal? Or do you have any other suggestions?

@dplore
Copy link
Member

dplore commented Aug 3, 2023

Instead of a boolean of is-virtual-gateway, you could add VIRTUAL_GATEWAY the enum for ipv4-address-type

Also add virtual-gateway-mac which is only valid when ipv4-address-type=VIRTUAL_GATEWAY

Example tree:

  +--rw interfaces
     +--rw interface* [name]
        +--rw oc-vlan:routed-vlan
           +--rw oc-ip:ipv4
                 +--rw oc-ip:addresses
                    +--rw oc-ip:address* [ip]
                       +--rw oc-ip:ip        -> ../config/ip
                       +--rw oc-ip:config
                       |  +--rw oc-ip:ip?              oc-inet:ipv4-address
                       |  +--rw oc-ip:prefix-length?   uint8
                       |  +--rw oc-ip:type?            ipv4-address-type  
                       |  +--rw oc-ip:virtual-gw-mac?            oc-yang:mac-address
                       +--ro oc-ip:state
                          +--ro oc-ip:ip?              oc-inet:ipv4-address
                          +--ro oc-ip:prefix-length?   uint8
                          +--ro oc-ip:type?            ipv4-address-type
                          +--rw oc-ip:virtual-gw-mac?            oc-yang:mac-address

Example config:

        "name": "Ethernet1/2/3",
        "subinterfaces": {
          "subinterface": [
            {
              "config": {
                "description": "my interface",
                "enabled": true,
                "index": 0,
              },
              "index": 0,
              "ipv4": {
                "addresses": {
                  "address": [
                    {
                      "config": {
                        "ip": "10.1.1.1",
                        "prefix-length": 24,
                        "type": "PRIMARY"
                      },
                      "ip": "10.1.1.1"
                    },
                    {
                      "config": {
                        "ip": "10.1.2.1",
                        "prefix-length": 32,
                        "type": "VIRTUAL_GATEWAY",
                        "virtual-gw-mac": "00:00:aa:11:22:33"
                      },
                      "ip": "10.1.2.1"
                    }
                  ]
                },
                "config": {
                  "enabled": true
                },
              },

@rolandphung
Copy link
Contributor

you could add VIRTUAL_GATEWAY the enum for ipv4-address-type

For IPv4, Arista has ip address virtual <prefix> secondary configuration. Unfortunately I wasn't able to find any public facing documents on this yet, but I have the an example configuration here:

interface Vlan10                          
   ip address virtual 1.2.2.1/24          
   ip address virtual 1.2.3.1/24 secondary

This means that if we go this route there should be a VIRTUAL_SECONDARY type for this address as well.

The only thing I'm wary about when combining physical and virtual addresses in a modeling point of view is that it becomes much harder to provide additional configuration that is specific to one or the other. Also it means that all containers under physical addresses (like VRRP) will also be "configurable" for these virtual addresses which can be confusing. I think a separate container for virtual-gateway would be cleaner.

@dplore
Copy link
Member

dplore commented Aug 9, 2023

you could add VIRTUAL_GATEWAY the enum for ipv4-address-type

For IPv4, Arista has ip address virtual <prefix> secondary configuration. Unfortunately I wasn't able to find any public facing documents on this yet, but I have the an example configuration here:

interface Vlan10                          
   ip address virtual 1.2.2.1/24          
   ip address virtual 1.2.3.1/24 secondary

This means that if we go this route there should be a VIRTUAL_SECONDARY type for this address as well.

The only thing I'm wary about when combining physical and virtual addresses in a modeling point of view is that it becomes much harder to provide additional configuration that is specific to one or the other. Also it means that all containers under physical addresses (like VRRP) will also be "configurable" for these virtual addresses which can be confusing. I think a separate container for virtual-gateway would be cleaner.

Ah ok, if there are multiple attributes (>1) specific to virtual-gateway, then I am ok with adding a container for virtual-gateway if. Seems like there are possibly two so far: a virtual gw mac and the secondary attribute.

Example model using a container with a list of virtual-gateway ip addresses:

  +--rw interfaces
     +--rw interface* [name]
        +--rw oc-vlan:routed-vlan
           +--rw oc-ip:ipv4
              +--rw oc-ip:addresses
                  +--rw oc-ip:address* [ip]
                          [... snip ...]
              +--rw oc-ip:virtual-gateways
                +--rw oc-ip:virtual-gateway* [ip]
                       +--rw oc-ip:ip        -> ../config/ip
                       +--rw oc-ip:config
                       |  +--rw oc-ip:ip?              oc-inet:ipv4-address
                       |  +--rw oc-ip:prefix-length?   uint8
                       |  +--rw oc-ip:virtual-gw-mac?            oc-yang:mac-address
                       |  +--rw oc-ip:secondary?            boolean
                       +--ro oc-ip:state
                          +--ro oc-ip:ip?              oc-inet:ipv4-address
                          +--ro oc-ip:prefix-length?   uint8
                          +--ro oc-ip:type?            ipv4-address-type
                          +--ro oc-ip:virtual-gw-mac?            oc-yang:mac-address
                          +--ro oc-ip:secondary?            boolean

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

Successfully merging this pull request may close these issues.

7 participants