diff --git a/docs/HLD/vpp-lag.md b/docs/HLD/vpp-lag.md
new file mode 100644
index 0000000..1954b68
--- /dev/null
+++ b/docs/HLD/vpp-lag.md
@@ -0,0 +1,84 @@
+# SONIC VPP LAG Bridging support
+Rev v0.1
+
+
+
+
+## Table of Contents
+
+1. [Revisions](#item-1)
+2. [Scope](#item-2)
+3. [Definitions/Abbreviations](#item-3)
+4. [Introduction](#item-4)
+5. [LAG and Bridging](#item-5)
+
+
+
+
+
+## Revisions
+
+| Rev | Date | Author(s) |
+|-----|------|-----------|
+|v0.1 | 25/02/2024 | Bendrapu Balareddy (Cisco), Sameer Nanajkar (Cisco) |
+
+
+
+
+
+
+## Scope
+This document describes the high level design of integrating LAG and bridging functionality between SONIC and VPP. It provides
+ - LAG
+ - 802.1Q bridging
+
+
+
+
+## Definitions/Abbreviations
+**VPP**: Vector Packet Processing (VPP) technology based high performance packet processing stack that can run on commodity CPUs. For more details see [What is VPP](https://wiki.fd.io/view/VPP/What_is_VPP%3F)
+
+**LAG**: Ling Aggregation Group
+
+
+
+
+
+
+## Introduction
+LAG functionality is supported in SONiC with port channel interfaces.
+VPP port channel supports modes as active-standby , active-active or LACP mode. But SONiC does not have a way program
+this through configuration. Hence the portchannel mode as default active-active by giving ROUND_ROBIN value. Similarly
+VPP supports different load balancing algorithms for distributing the traffic in active-active mode. But again SONIC
+does not support a way to configure any load balancing algorithm, hence it's programmed as BOND_API_LB_ALGO_L2 by default.
+If there is any defined requirement in future to use different load balancing algorithm to use by default, it can be
+changed accordingly.
+
+Some parameters the SONIC supports are not supported by VPP. The attributes like min-links for portchannel group, fast-rate
+etc are not supported by VPP.
+
+To enable LACP on VPP, the VPP should be rebuilt with LACP plugin added. Currently sonic-platform-vpp repo uses prebuilt
+vpp binary. Hence it needs some changes the way this repo is using the VPP
+
+
+
+![LAG Bridging](../LAG-Dot1q-Bridging-Topo.png)
+
+SONiC supports port channel interfaces. These interfaces can be configured for layer routing or as members of a vlan
+ - Access port
+ config vlan member add -u creates an un tagged bridge port. This will be translated to vpp in two steps
+ 1. creates a bridge with given vlan id as bridge id if the bridge with given id doesnot exist.
+ 2. set the port as member of bridge with appropriate tag rewrite
+ - Trunk port
+ config vlan member add creates a tagged port bridge port. This will be translated to vpp in three steps
+ 1. creates a bridge with given vlan id as bridge id if the bridge with given aid does not exist.
+ 2. vpp trunk port operation is achieved through vlan subinterface. A subinterface is created for this vlan id. Note
+ that this subinterface is only specific to vpp and does not appear in SONiC control plane data bases.
+ 3. set the vlan subinterface as bridge port
+
+
+## References
+
+[SONiC system architecture](https://github.com/sonic-net/SONiC/wiki/Architecture)\
+[What is VPP](https://s3-docs.fd.io/vpp/23.06/)
+
diff --git a/docs/LAG-Dot1q-Bridging-Topo.png b/docs/LAG-Dot1q-Bridging-Topo.png
new file mode 100644
index 0000000..d23424c
Binary files /dev/null and b/docs/LAG-Dot1q-Bridging-Topo.png differ
diff --git a/docs/README.LAG.dot1q.bridging.topo.md b/docs/README.LAG.dot1q.bridging.topo.md
new file mode 100644
index 0000000..eec13c4
--- /dev/null
+++ b/docs/README.LAG.dot1q.bridging.topo.md
@@ -0,0 +1,558 @@
+# LAG 8021q bridging Test
+
+
+
+SONiC-A connections
+```
+Host1-10.0.1.1/24--Ethernet0|-bvi10-10.0.1.10/24-|PortChannel10-trunk1 vlan 10 [members-Ethernet4,5]
+Host2-10.0.2.1/24--Ethernet1|-bvi20-10.0.2.20/24-| Ethernet3-trunk vlan20
+Host3-10.0.3.1/24--Ethernet2|------SONiC-A-------| Ethernet3-trunk vlan30
+```
+
+
+SONiC-B connections
+```
+ PortChannel10-trunk1 vlan 10 [members-Ethernet2,3] |SONiC-B|Ethernet1 trunk2 vlan 10
+ Ethernet0-trunk vlan20] |SONiC-B|Ethernet1 trunk2 vlan 20
+ Ethernet0-trunk vlan30 |SONiC-B|Ethernet1 trunk2 vlan 30
+```
+
+SONiC-C connections
+```
+Ethernet3 trunk2 vlan 10|SONIC-C|Ethernet0-------|Host4-10.0.1.2/24
+Ethernet3 trunk2 vlan 20|SONIC-C|Ethernet1-------|Host5-10.0.2.2/24
+Ethernet3 trunk2 vlan 30|SONiC-C|Ethernet2-------|Host6-10.0.3.2/24
+```
+
+Pre-requisites for testing
+
+Make sure the docker is installed on the Linux system. iproute2 and sudo packages should be installed.
+
+Load container images
+```
+docker load < docker-sonic-vpp.gz
+```
+
+Check if images are listed
+```
+docker images | grep "sonic-vpp\|pause"
+```
+
+Get the script to create and run the sonic container from the sonic-platform-vpp repo if you have not cloned the repo.
+```
+wget https://raw.githubusercontent.com/sonic-net/sonic-platform-vpp/main/start_sonic_vpp.sh
+```
+Set the execute bits of the downloaded script file
+```
+chmod +x start_sonic_vpp.sh
+
+```
+Else if you have already cloned the sonic-platform-repo you can copy the script to the local directory and use it.
+
+On the host create veth interface pairs for vpp and host
+
+```
+sudo ip link add name veth_ac1 type veth peer name ac1
+sudo ip link add name veth_ac2 type veth peer name ac2
+sudo ip link add name veth_ac3 type veth peer name ac3
+sudo ip link add name veth_ac4 type veth peer name ac4
+sudo ip link add name veth_ac5 type veth peer name ac5
+sudo ip link add name veth_ac6 type veth peer name ac6
+sudo ip link add name veth_pc_member1 type veth peer name pc_member1
+sudo ip link add name veth_pc_member2 type veth peer name pc_member2
+sudo ip link add name veth_trunk1 type veth peer name trunk1
+sudo ip link add name veth_trunk2 type veth peer name trunk2
+
+```
+
+Create network namespace for end hosts and inject one end of veth pair
+
+```
+sudo ip netns add host-1.0
+sudo ip netns add host-2.0
+sudo ip netns add host-3.0
+sudo ip netns add host-4.0
+sudo ip netns add host-5.0
+sudo ip netns add host-6.0
+sudo ip link set dev veth_ac1 netns host-1.0
+sudo ip link set dev veth_ac2 netns host-2.0
+sudo ip link set dev veth_ac3 netns host-3.0
+sudo ip link set dev veth_ac4 netns host-4.0
+sudo ip link set dev veth_ac5 netns host-5.0
+sudo ip link set dev veth_ac6 netns host-6.0
+```
+
+Configure IP addresses inside the host net namepaces
+
+```
+sudo ip netns exec host-1.0 bash
+ip link set dev veth_ac1 up
+ip addr add 10.0.1.1/24 dev veth_ac1
+ip addr add fd12:3456:789a:1::2/64 dev veth_ac1
+ip route add 10.0.2.0/24 via 10.0.1.10
+ip address show
+ip route show
+exit
+
+sudo ip netns exec host-2.0 bash
+ip link set dev veth_ac2 up
+ip addr add 10.0.2.1/24 dev veth_ac2
+ip addr add fd12:3456:789a:2::2/64 dev veth_ac2
+ip route add 10.0.1.0/24 via 10.0.2.20
+ip address show
+ip route show
+exit
+
+sudo ip netns exec host-3.0 bash
+ip link set dev veth_ac3 up
+ip addr add 10.0.3.1/24 dev veth_ac3
+ip addr add fd12:3456:789a:3::2/64 dev veth_ac3
+ip address show
+ip route show
+exit
+
+sudo ip netns exec host-4.0 bash
+ip link set dev veth_ac4 up
+ip addr add 10.0.1.2/24 dev veth_ac4
+ip addr add fd12:3456:789a:1::3/64 dev veth_ac4
+ip route add 10.0.2.0/24 via 10.0.1.10
+ip address show
+ip route show
+exit
+
+sudo ip netns exec host-5.0 bash
+ip link set dev veth_ac5 up
+ip addr add 10.0.2.2/24 dev veth_ac5
+ip addr add fd12:3456:789a:2::3/64 dev veth_ac5
+ip route add 10.0.1.0/24 via 10.0.2.20
+ip address show
+ip route show
+exit
+
+sudo ip netns exec host-6.0 bash
+ip link set dev veth_ac6 up
+ip addr add 10.0.3.2/24 dev veth_ac6
+ip addr add fd12:3456:789a:3::3/64 dev veth_ac6
+ip address show
+ip route show
+exit
+```
+
+Now start the sonic container and pass the veth interfaces to sonic-vpp
+```
+sudo ./start_sonic_vpp.sh start -n SONIC-A -i ac1,ac2,ac3,trunk1,pc_member1,pc_member2
+```
+
+start the second sonic container and pass the veth interfaces to sonic-vpp
+```
+sudo ./start_sonic_vpp.sh start -n SONIC-B -i veth_trunk1,veth_trunk2,veth_pc_member1,veth_pc_member2
+```
+
+start the third sonic container and pass the veth interfaces to sonic-vpp
+```
+sudo ./start_sonic_vpp.sh start -n SONIC-C -i ac4,ac5,ac6,trunk2
+```
+
+Get into SONIC-A container and configure vlan and vlan bridging
+
+SONIC-A:
+```
+docker exec -it SONIC-A /bin/bash
+show interface status
+config interface startup Ethernet0
+config interface startup Ethernet1
+config interface startup Ethernet2
+config interface startup Ethernet3
+config interface startup Ethernet4
+config interface startup Ethernet5
+
+config portchannel add PortChannel10
+config portchannel member add PortChannel10 Ethernet4
+config portchannel member add PortChannel10 Ethernet5
+
+config vlan add 10
+config vlan member add -u 10 Ethernet0
+config vlan member add 10 PortChannel10
+
+config vlan add 20
+config vlan member add -u 20 Ethernet1
+config vlan member add 20 Ethernet3
+
+config vlan add 30
+config vlan member add -u 30 Ethernet2
+config vlan member add 30 Ethernet3
+
+config interface ip add Vlan10 10.0.1.10/24
+config interface ip add Vlan20 10.0.2.20/24
+```
+
+Get into SONIC-B container and configure vlan, vlan bridging
+
+SONIC-B:
+```
+docker exec -it SONIC-B /bin/bash
+show interface status
+config interface startup Ethernet0
+config interface startup Ethernet1
+config interface startup Ethernet2
+config interface startup Ethernet3
+
+config portchannel add PortChannel10
+config portchannel member add PortChannel10 Ethernet1
+config portchannel member add PortChannel10 Ethernet2
+
+config vlan add 10
+config vlan member add 10 PortChannel10
+config vlan member add 10 Ethernet3
+
+config vlan add 20
+config vlan member add 20 Ethernet0
+config vlan member add 20 Ethernet3
+
+config vlan add 30
+config vlan member add 30 Ethernet0
+config vlan member add 30 Ethernet3
+```
+
+Get into SONIC-C container and configure vlan, vlan bridging
+
+SONIC-C:
+```
+docker exec -it SONIC-C /bin/bash
+show interface status
+config interface startup Ethernet0
+config interface startup Ethernet1
+config interface startup Ethernet2
+config interface startup Ethernet3
+
+config vlan add 10
+config vlan member add -u 10 Ethernet0
+config vlan member add 10 Ethernet3
+
+config vlan add 20
+config vlan member add -u 20 Ethernet1
+config vlan member add 20 Ethernet3
+
+config vlan add 30
+config vlan member add -u 30 Ethernet2
+config vlan member add 30 Ethernet3
+```
+
+Test the SONiC vlan briding function across 3 VLAN bridge domains
+
+```
+sudo ip netns exec host-1.0 bash
+ping -c5 10.0.1.2 -- same bridge domain
+ping -c5 10.0.2.1 -- route to different bridge domain
+ping -c5 10.0.2.2 -- route to different bridge domain
+ping -c5 10.0.3.1 -- ping fails
+ping -c5 10.0.3.2 -- ping fails
+exit
+
+sudo ip netns exec host-2.0 bash
+ping -c5 10.0.2.2 -- same bridge domain
+ping -c5 10.0.1.1 -- route to different bridge domain
+ping -c5 10.0.1.2 -- route to different bridge domain
+ping -c5 10.0.3.1 -- ping fails as no routing for this
+ping -c5 10.0.3.2 -- ping fail as no routing for this
+exit
+
+sudo ip netns exec host-3.0 bash
+ping -c5 10.0.3.2
+ping6 fd12:3456:789a:3::3 -c 5
+ping -c5 10.0.1.1 -- ping fails as no routing for this
+ping -c5 10.0.1.2 -- ping fails as no routing for this
+ping -c5 10.0.2.1 -- ping fails as no routing for this
+ping -c5 10.0.2.2 -- ping fails as no routing for this
+exit
+
+sudo ip netns exec host-4.0 bash
+ping -c5 10.0.1.1
+ping -c5 10.0.2.1 -- route to different bridge domain
+ping -c5 10.0.2.2 -- route to different bridge domain
+ping -c5 10.0.3.1 -- ping fails as no routing for this
+ping -c5 10.0.3.2 -- ping fails as no routing for this
+exit
+
+sudo ip netns exec host-5.0 bash
+ping -c5 10.0.2.1
+ping -c5 10.0.1.1 -- route to different bridge domain
+ping -c5 10.0.1.2 -- route to different bridge domain
+ping -c5 10.0.3.1 -- ping fails as no routing for this
+ping -c5 10.0.3.2 -- ping fails as no routing for this
+exit
+
+sudo ip netns exec host-6.0 bash
+ping -c5 10.0.3.1
+ping6 -c5 fd12:3456:789a:3::3
+ping -c5 10.0.1.1 -- ping fails as no routing for this
+ping -c5 10.0.1.2 -- ping fails as no routing for this
+ping -c5 10.0.2.1 -- ping fails as no routing for this
+ping -c5 10.0.2.2 -- ping fails as no routing for this
+exit
+
+```
+
+You should see the ping reachability from host1 to host4, host2 to host5 and host3 to host6.
+
+Use below command to stop the sonic-vpp containers
+```
+sudo ./start_sonic_vpp.sh stop -n sonic-br1
+sudo ./start_sonic_vpp.sh stop -n sonic-br2
+sudo ./start_sonic_vpp.sh stop -n sonic-br3
+```
+
+Show command outputs sonic-br1
+```
+show interface status
+```
+```
+ Interface Lanes Speed MTU FEC Alias Vlan Oper Admin Type Asym PFC
+ +--------------------------------------------------------------------------------------------------------+
+ Ethernet0 25,26,27,28 100G 9100 N/A fortyGigE0/0 routed up down N/A N/A
+ Ethernet1 29,30,31,32 100G 9100 N/A fortyGigE0/4 routed up down N/A N/A
+ Ethernet2 33,34,35,36 100G 9100 N/A fortyGigE0/8 routed up down N/A N/A
+ Ethernet3 37,38,39,40 100G 9100 N/A fortyGigE0/12 routed up down N/A N/A
+ Ethernet4 45,46,47,48 100G 9100 N/A fortyGigE0/16 routed up down N/A N/A
+ Ethernet5 41,42,43,44 100G 9100 N/A fortyGigE0/20 routed up down N/A N/A
+```
+```
+show vlan brief
+```
+```
++-----------+--------------+---------------+----------------+-------------+
+| VLAN ID | IP Address | Ports | Port Tagging | Proxy ARP |
++===========+==============+===============+================+=============+
+| 10 | 10.0.1.10/24 | Ethernet0 | untagged | disabled |
+| | | PortChannel10 | tagged | |
++-----------+--------------+---------------+----------------+-------------+
+| 20 | 10.0.2.20/24 | Ethernet1 | untagged | disabled |
+| | | Ethernet3 | tagged | |
++-----------+--------------+---------------+----------------+-------------+
+| 30 | | Ethernet2 | untagged | disabled |
+| | | Ethernet3 | tagged | |
++-----------+--------------+---------------+----------------+-------------+
+```
+```
+show vlan config
+```
+```
+Name VID Member Mode
+------ ----- --------- --------
+Vlan10 10 Ethernet0 untagged
+Vlan10 10 PortChannel10 tagged
+Vlan20 20 Ethernet1 untagged
+Vlan20 20 Ethernet3 tagged
+Vlan30 30 Ethernet2 untagged
+Vlan30 30 Ethernet3 tagged
+```
+```
+vppctl show bridge
+```
+```
+ BD-ID Index BSN Age(min) Learning U-Forwrd UU-Flood Flooding ARP-Term arp-ufwd Learn-co Learn-li BVI-Intf
+ 10 1 0 off on on flood on off off 0 16777216 N/A
+ 20 2 0 off on on flood on off off 0 16777216 N/A
+ 30 3 0 off on on flood on off off 1 16777216 N/A
+```
+```
+vppctl show bridge 10 detail
+```
+```
+ BD-ID Index BSN Age(min) Learning U-Forwrd UU-Flood Flooding ARP-Term arp-ufwd Learn-co Learn-li BVI-Intf
+ 10 1 0 off on on flood on on off 0 16777216 bvi10
+span-l2-input l2-input-classify l2-input-feat-arc l2-policer-classify l2-input-acl vpath-input-l2 l2-ip-qos-record l2-input-vtr l2-learn l2-rw l2-fwd l2-flood arp-term-l2bd l2-flood l2-output
+
+ Interface If-idx ISN SHG BVI TxFlood VLAN-Tag-Rewrite
+ bvi10 19 1 0 * * push-1 dot1q 10
+ host-ac1 1 1 0 - * push-1 dot1q 10
+ BondEthernet0.10 14 1 0 - * none
+
+ IP4/IP6 to MAC table for ARP Termination
+```
+```
+vppctl show bridge 20 detail
+```
+```
+ BD-ID Index BSN Age(min) Learning U-Forwrd UU-Flood Flooding ARP-Term arp-ufwd Learn-co Learn-li BVI-Intf
+ 20 2 0 off on on flood on on off 0 16777216 bvi20
+span-l2-input l2-input-classify l2-input-feat-arc l2-policer-classify l2-input-acl vpath-input-l2 l2-ip-qos-record l2-input-vtr l2-learn l2-rw l2-fwd l2-flood arp-term-l2bd l2-flood l2-output
+
+ Interface If-idx ISN SHG BVI TxFlood VLAN-Tag-Rewrite
+ bvi20 20 1 0 * * push-1 dot1q 20
+ host-ac2 2 1 0 - * push-1 dot1q 20
+ host-trunk1.20 15 1 0 - * none
+
+ IP4/IP6 to MAC table for ARP Termination
+```
+```
+vppctl show bridge 30 detail
+```
+```
+ BD-ID Index BSN Age(min) Learning U-Forwrd UU-Flood Flooding ARP-Term arp-ufwd Learn-co Learn-li BVI-Intf
+ 30 3 0 off on on flood on off off 0 16777216 N/A
+span-l2-input l2-input-classify l2-input-feat-arc l2-policer-classify l2-input-acl vpath-input-l2 l2-ip-qos-record l2-input-vtr l2-learn l2-rw l2-fwd l2-flood l2-flood l2-output
+
+ Interface If-idx ISN SHG BVI TxFlood VLAN-Tag-Rewrite
+ host-ac3 3 1 0 - * push-1 dot1q 30
+ host-trunk1.30 17 1 0 - * none
+```
+```
+vppctl show ip4 neighbors
+```
+```
+
+ Time IP Flags Ethernet Interface
+ 17703.4524 10.0.1.2 D 52:84:76:96:2c:b7 bvi10
+ 17717.2684 10.0.1.1 D 6e:21:47:49:58:49 bvi10
+ 17693.9802 10.0.2.1 D da:9c:93:33:db:af bvi20
+ 17717.0202 10.0.2.2 D 7e:ef:f5:5c:0f:2a bvi20
+```
+```
+vppctl show interfaces
+```
+```
+ Name Idx State MTU (L3/IP4/IP6/MPLS) Counter Count
+BondEthernet0 13 up 9000/0/0/0
+BondEthernet0.10 14 up 0/0/0/0
+bvi10 19 up 9000/0/0/0
+bvi20 20 up 9000/0/0/0
+host-ac1 1 up 9122/0/0/0
+host-ac2 2 up 9122/0/0/0
+host-ac3 3 up 9122/0/0/0
+host-pc_member1 5 up 9122/0/0/0
+host-pc_member2 6 up 9122/0/0/0
+host-trunk1 4 up 9122/0/0/0
+host-trunk1.20 15 up 0/0/0/0
+host-trunk1.30 17 up 0/0/0/0
+local0 0 down 0/0/0/0
+tap1 8 up 9000/0/0/0
+tap2 7 up 9000/0/0/0
+tap3 9 up 9000/0/0/0
+tap4 10 up 9000/0/0/0
+tap4.20 16 up 0/0/0/0
+tap4.30 18 up 0/0/0/0
+tap5 12 up 9000/0/0/0
+tap6 11 up 9000/0/0/0
+```
+```
+ip addr show
+```
+```
+60: Vlan10@Bridge: mtu 9100 qdisc noqueue state UP group default qlen 1000
+ link/ether 02:42:ac:11:00:05 brd ff:ff:ff:ff:ff:ff
+ inet 10.0.1.10/24 brd 10.0.1.255 scope global Vlan10
+ valid_lft forever preferred_lft forever
+ inet6 fd12:3456:789a:1::1/64 scope global
+ valid_lft forever preferred_lft forever
+ inet6 fe80::42:acff:fe11:5/64 scope link
+ valid_lft forever preferred_lft forever
+61: Vlan20@Bridge: mtu 9100 qdisc noqueue state UP group default qlen 1000
+ link/ether 02:42:ac:11:00:05 brd ff:ff:ff:ff:ff:ff
+ inet 10.0.2.20/24 brd 10.0.2.255 scope global Vlan20
+ valid_lft forever preferred_lft forever
+ inet6 fd12:3456:789a:2::1/64 scope global
+ valid_lft forever preferred_lft forever
+ inet6 fe80::42:acff:fe11:5/64 scope link
+ valid_lft forever preferred_lft forever
+```
+
+```
+vppctl show ip fib
+```
+```
+
+ipv4-VRF:0, fib_index:0, flow hash:[src dst sport dport proto flowlabel ] epoch:0 flags:none locks:[adjacency:1, default-route:1, ]
+0.0.0.0/0
+ unicast-ip4-chain
+ [@0]: dpo-load-balance: [proto:ip4 index:1 buckets:1 uRPF:0 to:[0:0]]
+ [0] [@0]: dpo-drop ip4
+0.0.0.0/32
+ unicast-ip4-chain
+ [@0]: dpo-load-balance: [proto:ip4 index:2 buckets:1 uRPF:1 to:[0:0]]
+ [0] [@0]: dpo-drop ip4
+10.0.1.0/32
+ unicast-ip4-chain
+ [@0]: dpo-load-balance: [proto:ip4 index:9 buckets:1 uRPF:9 to:[0:0]]
+ [0] [@0]: dpo-drop ip4
+10.0.1.1/32
+ unicast-ip4-chain
+ [@0]: dpo-load-balance: [proto:ip4 index:17 buckets:1 uRPF:20 to:[5:420]]
+ [0] [@5]: ipv4 via 10.0.1.1 bvi10: mtu:9000 next:10 flags:[] 6e21474958490242ac1100050800
+10.0.1.2/32
+ unicast-ip4-chain
+ [@0]: dpo-load-balance: [proto:ip4 index:19 buckets:1 uRPF:22 to:[1:84]]
+ [0] [@5]: ipv4 via 10.0.1.2 bvi10: mtu:9000 next:10 flags:[] 528476962cb70242ac1100050800
+10.0.1.0/24
+ unicast-ip4-chain
+ [@0]: dpo-load-balance: [proto:ip4 index:8 buckets:1 uRPF:8 to:[2:168]]
+ [0] [@4]: ipv4-glean: [src:10.0.1.0/24] bvi10: mtu:9000 next:1 flags:[] ffffffffffff0242ac1100050806
+10.0.1.10/32
+ unicast-ip4-chain
+ [@0]: dpo-load-balance: [proto:ip4 index:11 buckets:1 uRPF:13 to:[0:0]]
+ [0] [@12]: dpo-receive: 10.0.1.10 on bvi10
+10.0.1.255/32
+ unicast-ip4-chain
+ [@0]: dpo-load-balance: [proto:ip4 index:10 buckets:1 uRPF:11 to:[0:0]]
+ [0] [@0]: dpo-drop ip4
+10.0.2.0/32
+ unicast-ip4-chain
+ [@0]: dpo-load-balance: [proto:ip4 index:13 buckets:1 uRPF:15 to:[0:0]]
+ [0] [@0]: dpo-drop ip4
+10.0.2.1/32
+ unicast-ip4-chain
+ [@0]: dpo-load-balance: [proto:ip4 index:18 buckets:1 uRPF:21 to:[1:84]]
+ [0] [@5]: ipv4 via 10.0.2.1 bvi20: mtu:9000 next:9 flags:[] da9c9333dbaf0242ac1100050800
+10.0.2.2/32
+ unicast-ip4-chain
+ [@0]: dpo-load-balance: [proto:ip4 index:16 buckets:1 uRPF:18 to:[6:504]]
+ [0] [@5]: ipv4 via 10.0.2.2 bvi20: mtu:9000 next:9 flags:[] 7eeff55c0f2a0242ac1100050800
+10.0.2.0/24
+ unicast-ip4-chain
+ [@0]: dpo-load-balance: [proto:ip4 index:12 buckets:1 uRPF:14 to:[2:168]]
+ [0] [@4]: ipv4-glean: [src:10.0.2.0/24] bvi20: mtu:9000 next:2 flags:[] ffffffffffff0242ac1100050806
+10.0.2.20/32
+ unicast-ip4-chain
+ [@0]: dpo-load-balance: [proto:ip4 index:15 buckets:1 uRPF:19 to:[0:0]]
+ [0] [@12]: dpo-receive: 10.0.2.20 on bvi20
+10.0.2.255/32
+ unicast-ip4-chain
+ [@0]: dpo-load-balance: [proto:ip4 index:14 buckets:1 uRPF:17 to:[0:0]]
+ [0] [@0]: dpo-drop ip4
+224.0.0.0/4
+ unicast-ip4-chain
+ [@0]: dpo-load-balance: [proto:ip4 index:4 buckets:1 uRPF:3 to:[0:0]]
+ [0] [@0]: dpo-drop ip4
+240.0.0.0/4
+ unicast-ip4-chain
+ [@0]: dpo-load-balance: [proto:ip4 index:3 buckets:1 uRPF:2 to:[0:0]]
+ [0] [@0]: dpo-drop ip4
+255.255.255.255/32
+ unicast-ip4-chain
+ [@0]: dpo-load-balance: [proto:ip4 index:5 buckets:1 uRPF:4 to:[0:0]]
+ [0] [@0]: dpo-drop ip4
+```
+
+```
+check the connectivity on portchannel interface by starting ping between vlan 10 hosts
+
+ping 10.0.1.2
+PING 10.0.1.2 (10.0.1.2) 56(84) bytes of data.
+64 bytes from 10.0.1.2: icmp_seq=1 ttl=64 time=27.7 ms
+64 bytes from 10.0.1.2: icmp_seq=2 ttl=64 time=41.6 ms
+
+check the packets on portchannel member interfaces
+
+1. shutdown one member interface of portchannel, verify the connectivity still fine and verify portchannel member counters
+2. shutdown second member interface of portchannel, verify the connectivity is lost and verify portchannel member counters
+3. bring up second member interface of portchannel back, verify the connectivity is restored and verify portchannel member counters
+4. bring up other member interface of portchannel back, verify the connectivity is restored and verify portchannel member counters
+```
+Verification of packet on VPP data plane for vlan tagging
+Start the ping and then do show trace
+
+```
+vppctl
+trace add af-packet-input 10
+show trace
+```
diff --git a/platform/saivpp/vpplib/SwitchStateBase.cpp b/platform/saivpp/vpplib/SwitchStateBase.cpp
index 646133e..1433425 100644
--- a/platform/saivpp/vpplib/SwitchStateBase.cpp
+++ b/platform/saivpp/vpplib/SwitchStateBase.cpp
@@ -253,6 +253,19 @@ sai_status_t SwitchStateBase::create(
return createVlanMember(object_id, switch_id, attr_count, attr_list);
}
+ if (object_type == SAI_OBJECT_TYPE_LAG )
+ {
+ sai_object_id_t object_id;
+ sai_deserialize_object_id(serializedObjectId, object_id);
+ return createLag(object_id, switch_id, attr_count, attr_list);
+ }
+ if (object_type == SAI_OBJECT_TYPE_LAG_MEMBER)
+ {
+ sai_object_id_t object_id;
+ sai_deserialize_object_id(serializedObjectId, object_id);
+ return createLagMember(object_id, switch_id, attr_count, attr_list);
+ }
+
return create_internal(object_type, serializedObjectId, switch_id, attr_count, attr_list);
}
@@ -527,6 +540,18 @@ sai_status_t SwitchStateBase::remove(
sai_deserialize_object_id(serializedObjectId, objectId);
return removeVlanMember(objectId);
}
+ else if (object_type == SAI_OBJECT_TYPE_LAG)
+ {
+ sai_object_id_t objectId;
+ sai_deserialize_object_id(serializedObjectId, objectId);
+ return removeLag(objectId);
+ }
+ else if (object_type == SAI_OBJECT_TYPE_LAG_MEMBER)
+ {
+ sai_object_id_t objectId;
+ sai_deserialize_object_id(serializedObjectId, objectId);
+ return removeLagMember(objectId);
+ }
return remove_internal(object_type, serializedObjectId);
}
diff --git a/platform/saivpp/vpplib/SwitchStateBase.h b/platform/saivpp/vpplib/SwitchStateBase.h
index 87f056b..473873e 100644
--- a/platform/saivpp/vpplib/SwitchStateBase.h
+++ b/platform/saivpp/vpplib/SwitchStateBase.h
@@ -163,6 +163,32 @@ namespace saivpp
_In_ const sai_attribute_t *attr_list);
sai_status_t vpp_delete_bvi_interface(
_In_ sai_object_id_t bvi_obj_id);
+ sai_status_t createLag(
+ _In_ sai_object_id_t object_id,
+ _In_ sai_object_id_t switch_id,
+ _In_ uint32_t attr_count,
+ _In_ const sai_attribute_t *attr_list);
+ sai_status_t vpp_create_lag(
+ _In_ sai_object_id_t lag_id,
+ _In_ uint32_t attr_count,
+ _In_ const sai_attribute_t *attr_list);
+ sai_status_t removeLag(
+ _In_ sai_object_id_t lag_oid);
+ sai_status_t vpp_remove_lag(
+ _In_ sai_object_id_t lag_oid);
+ sai_status_t createLagMember(
+ _In_ sai_object_id_t object_id,
+ _In_ sai_object_id_t switch_id,
+ _In_ uint32_t attr_count,
+ _In_ const sai_attribute_t *attr_list);
+ sai_status_t vpp_create_lag_member(
+ _In_ uint32_t attr_count,
+ _In_ const sai_attribute_t *attr_list);
+ sai_status_t removeLagMember(
+ _In_ sai_object_id_t lag_member_oid);
+ sai_status_t vpp_remove_lag_member(
+ _In_ sai_object_id_t lag_member_oid);
+
protected:
virtual sai_status_t create_port_dependencies(
@@ -1016,6 +1042,8 @@ namespace saivpp
void populate_if_mapping();
const char *tap_to_hwif_name(const char *name);
const char *hwif_to_tap_name(const char *name);
+ uint32_t lag_to_bond_if_idx (const sai_object_id_t lag_id);
+ int remove_lag_to_bond_entry (const sai_object_id_t lag_id);
void vppProcessEvents ();
void startVppEventsThread();
@@ -1029,6 +1057,7 @@ namespace saivpp
bool m_run_vpp_events_thread = true;
bool VppEventsThreadStarted = false;
std::shared_ptr m_vpp_thread;
+ std::map m_lag_bond_map;
private:
static int currentMaxInstance;
diff --git a/platform/saivpp/vpplib/SwitchStateBaseFdb.cpp b/platform/saivpp/vpplib/SwitchStateBaseFdb.cpp
index 4ba2b90..6552949 100644
--- a/platform/saivpp/vpplib/SwitchStateBaseFdb.cpp
+++ b/platform/saivpp/vpplib/SwitchStateBaseFdb.cpp
@@ -678,7 +678,7 @@ sai_status_t SwitchStateBase::vpp_create_vlan_member(
if (obj_type != SAI_OBJECT_TYPE_BRIDGE_PORT)
{
- SWSS_LOG_ERROR("SAI_VLAN_MEMBER_ATTR_BRIDGE_PORT_ID=%s expected to be PORT but is: %s",
+ SWSS_LOG_ERROR("SAI_VLAN_MEMBER_ATTR_BRIDGE_PORT_ID=%s expected to be BRIDGE PORT but is: %s",
sai_serialize_object_id(br_port_id).c_str(),
sai_serialize_object_type(obj_type).c_str());
@@ -686,28 +686,43 @@ sai_status_t SwitchStateBase::vpp_create_vlan_member(
}
const char *hwifname = nullptr;
+ uint32_t lag_swif_idx;
+
auto br_port_attrs = m_objectHash.at(SAI_OBJECT_TYPE_BRIDGE_PORT).at(sai_serialize_object_id(br_port_id));
auto meta = sai_metadata_get_attr_metadata(SAI_OBJECT_TYPE_BRIDGE_PORT, SAI_BRIDGE_PORT_ATTR_PORT_ID);
auto bp_attr = br_port_attrs[meta->attridname];
auto port_id = bp_attr->getAttr()->value.oid;
obj_type = objectTypeQuery(port_id);
- if (obj_type != SAI_OBJECT_TYPE_PORT)
+ if (obj_type != SAI_OBJECT_TYPE_PORT && obj_type != SAI_OBJECT_TYPE_LAG )
{
- SWSS_LOG_NOTICE("SAI_BRIDGE_PORT_ATTR_PORT_ID=%s expected to be PORT but is: %s",
+ SWSS_LOG_NOTICE("SAI_BRIDGE_PORT_ATTR_PORT_ID=%s expected to be PORT or LAG but is: %s",
sai_serialize_object_id(port_id).c_str(),
sai_serialize_object_type(obj_type).c_str());
return SAI_STATUS_FAILURE;
}
- std::string if_name;
- bool found = getTapNameFromPortId(port_id, if_name);
- if (found == true)
+ if (obj_type == SAI_OBJECT_TYPE_PORT)
{
- hwifname = tap_to_hwif_name(if_name.c_str());
- }else {
- SWSS_LOG_NOTICE("No ports found for bridge port id :%s",sai_serialize_object_id(br_port_id).c_str());
- return SAI_STATUS_FAILURE;
+ std::string if_name;
+ bool found = getTapNameFromPortId(port_id, if_name);
+ if (found == true)
+ {
+ hwifname = tap_to_hwif_name(if_name.c_str());
+ }else {
+ SWSS_LOG_NOTICE("No ports found for bridge port id :%s",sai_serialize_object_id(br_port_id).c_str());
+ return SAI_STATUS_FAILURE;
+ }
+ } else if (obj_type == SAI_OBJECT_TYPE_LAG) {
+ lag_swif_idx = lag_to_bond_if_idx(port_id);
+ SWSS_LOG_NOTICE("lag swif idx :%d",lag_swif_idx);
+ hwifname = vpp_get_swif_name(lag_swif_idx);
+ SWSS_LOG_NOTICE("lag swif idx :%d swif_name:%s",lag_swif_idx, hwifname);
+ if (hwifname == NULL)
+ {
+ SWSS_LOG_NOTICE("LAG is not found for bridge port id :%s",sai_serialize_object_id(br_port_id).c_str());
+ return SAI_STATUS_FAILURE;
+ }
}
auto attr_vlan_member = sai_metadata_get_attr_by_id(SAI_VLAN_MEMBER_ATTR_VLAN_ID, attr_count, attr_list);
@@ -865,24 +880,37 @@ sai_status_t SwitchStateBase::vpp_remove_vlan_member(
auto port_id = bp_attr->getAttr()->value.oid;
obj_type = objectTypeQuery(port_id);
- if (obj_type != SAI_OBJECT_TYPE_PORT)
+ if (obj_type != SAI_OBJECT_TYPE_PORT && obj_type != SAI_OBJECT_TYPE_LAG)
{
- SWSS_LOG_NOTICE("SAI_BRIDGE_PORT_ATTR_PORT_ID=%s expected to be PORT but is: %s",
+ SWSS_LOG_NOTICE("SAI_BRIDGE_PORT_ATTR_PORT_ID=%s expected to be PORT or LAG but is: %s",
sai_serialize_object_id(port_id).c_str(),
sai_serialize_object_type(obj_type).c_str());
return SAI_STATUS_FAILURE;
}
- std::string if_name;
- bool found = getTapNameFromPortId(port_id, if_name);
- if (found == true)
+
+ if (obj_type == SAI_OBJECT_TYPE_PORT)
{
- hw_ifname = tap_to_hwif_name(if_name.c_str());
- }else {
- SWSS_LOG_NOTICE("No ports found for bridge port id :%s",sai_serialize_object_id(br_port_oid).c_str());
- return SAI_STATUS_FAILURE;
+ std::string if_name;
+ bool found = getTapNameFromPortId(port_id, if_name);
+ if (found == true)
+ {
+ hw_ifname = tap_to_hwif_name(if_name.c_str());
+ }else {
+ SWSS_LOG_NOTICE("No ports found for bridge port id :%s",sai_serialize_object_id(br_port_oid).c_str());
+ return SAI_STATUS_FAILURE;
+ }
+ } else if (obj_type == SAI_OBJECT_TYPE_LAG) {
+ uint32_t lag_swif_idx = lag_to_bond_if_idx(port_id);
+ SWSS_LOG_NOTICE("lag swif idx :%d",lag_swif_idx);
+ hw_ifname = vpp_get_swif_name(lag_swif_idx);
+ SWSS_LOG_NOTICE("lag swif idx :%d swif_name:%s",lag_swif_idx, hw_ifname);
+ if (hw_ifname == NULL)
+ {
+ SWSS_LOG_NOTICE("LAG port is not found for bridge port id :%s",sai_serialize_object_id(port_id).c_str());
+ return SAI_STATUS_FAILURE;
+ }
}
-
attr.id = SAI_VLAN_MEMBER_ATTR_VLAN_TAGGING_MODE;
status = get(SAI_OBJECT_TYPE_VLAN_MEMBER, vlan_member_oid, 1, &attr);
@@ -1082,3 +1110,264 @@ sai_status_t SwitchStateBase::vpp_delete_bvi_interface(
return SAI_STATUS_SUCCESS;
}
+
+uint32_t SwitchStateBase::lag_to_bond_if_idx (const sai_object_id_t lag_id)
+{
+ auto it = m_lag_bond_map.find(lag_id);
+
+ if (it == m_lag_bond_map.end())
+ {
+ SWSS_LOG_ERROR("failed to find bond if idx for lag id: %x",lag_id);
+ return ~0;
+ }
+ return it->second;
+}
+
+int SwitchStateBase::remove_lag_to_bond_entry(const sai_object_id_t lag_oid)
+{
+ auto it = m_lag_bond_map.find(lag_oid);
+
+ if (it == m_lag_bond_map.end())
+ {
+ SWSS_LOG_ERROR("failed to find lag swif index for : %s", sai_serialize_object_id(lag_oid).c_str());
+ return ~0;
+ }
+
+ SWSS_LOG_NOTICE("Removing lag object swif index: %s", sai_serialize_object_id(lag_oid).c_str());
+ m_lag_bond_map.erase(it);
+ return 0;
+}
+
+sai_status_t SwitchStateBase:: createLag(
+ _In_ sai_object_id_t object_id,
+ _In_ sai_object_id_t switch_id,
+ _In_ uint32_t attr_count,
+ _In_ const sai_attribute_t *attr_list)
+{
+ SWSS_LOG_ENTER();
+
+ auto sid = sai_serialize_object_id(object_id);
+ CHECK_STATUS(create_internal(SAI_OBJECT_TYPE_LAG, sid, switch_id, attr_count, attr_list));
+ return vpp_create_lag(object_id, attr_count, attr_list);
+
+}
+
+sai_status_t SwitchStateBase::vpp_create_lag(
+ _In_ sai_object_id_t lag_id,
+ _In_ uint32_t attr_count,
+ _In_ const sai_attribute_t *attr_list)
+{
+ uint32_t bond_id, mode, lb;
+ uint32_t swif_idx = ~0;
+ const char *hw_ifname;
+ SWSS_LOG_ENTER();
+
+ //set mode and lb. ONiC config does not have provision to pass mode and load balancing algorithm
+ mode = VPP_BOND_API_MODE_ROUND_ROBIN;
+
+ //if LACP is to be enabled in VPP
+ //mode = VPP_BOND_API_MODE_LACP;
+ lb = VPP_BOND_API_LB_ALGO_L2;
+ bond_id = ~0;
+
+ create_bond_interface(bond_id, mode, lb, &swif_idx);
+ SWSS_LOG_NOTICE("vpp bond interfae created if index:%d\n", swif_idx);
+ //update the lag to bond map
+ m_lag_bond_map[lag_id] = swif_idx;
+ refresh_interfaces_list();
+
+ // Set the bond interface state up
+ hw_ifname = vpp_get_swif_name(swif_idx);
+ SWSS_LOG_NOTICE("Setting lag hw interface state to up :%s",hw_ifname);
+ interface_set_state(hw_ifname, true);
+ return SAI_STATUS_SUCCESS;
+}
+
+sai_status_t SwitchStateBase:: removeLag(
+ _In_ sai_object_id_t lag_oid)
+{
+ SWSS_LOG_ENTER();
+
+ vpp_remove_lag(lag_oid);
+ auto sid = sai_serialize_object_id(lag_oid);
+ CHECK_STATUS(remove_internal(SAI_OBJECT_TYPE_LAG, sid));
+ return SAI_STATUS_SUCCESS;
+}
+
+sai_status_t SwitchStateBase::vpp_remove_lag(
+ _In_ sai_object_id_t lag_oid)
+{
+ SWSS_LOG_ENTER();
+
+ uint32_t lag_swif_idx = lag_to_bond_if_idx(lag_oid);
+ SWSS_LOG_NOTICE("lag swif idx :%d",lag_swif_idx);
+ auto lag_ifname = vpp_get_swif_name(lag_swif_idx);
+ SWSS_LOG_NOTICE("lag swif idx :%d swif_name:%s",lag_swif_idx, lag_ifname);
+ if (lag_ifname == NULL)
+ {
+ SWSS_LOG_NOTICE("LAG interface name is not found for LAG PORT :%s",sai_serialize_object_id(lag_oid).c_str());
+ return SAI_STATUS_FAILURE;
+ }
+
+ //Delete the Bond interface
+ delete_bond_interface(lag_ifname);
+ remove_lag_to_bond_entry(lag_oid);
+
+ return SAI_STATUS_SUCCESS;
+}
+
+sai_status_t SwitchStateBase:: createLagMember(
+ _In_ sai_object_id_t object_id,
+ _In_ sai_object_id_t switch_id,
+ _In_ uint32_t attr_count,
+ _In_ const sai_attribute_t *attr_list)
+{
+ SWSS_LOG_ENTER();
+
+ auto sid = sai_serialize_object_id(object_id);
+
+ CHECK_STATUS(create_internal(SAI_OBJECT_TYPE_LAG_MEMBER, sid, switch_id, attr_count, attr_list));
+ return vpp_create_lag_member(attr_count, attr_list);
+}
+
+sai_status_t SwitchStateBase::vpp_create_lag_member(
+ _In_ uint32_t attr_count,
+ _In_ const sai_attribute_t *attr_list)
+{
+ bool is_long_timeout = false;
+ bool is_passive = false;
+ uint32_t bond_if_idx;
+ sai_object_id_t lag_oid, lag_port_oid;
+ SWSS_LOG_ENTER();
+
+ //Get the bond interface index from attr SAI_LAG_MEMBER_ATTR_LAG_ID
+ auto attr_type = sai_metadata_get_attr_by_id(SAI_LAG_MEMBER_ATTR_LAG_ID, attr_count, attr_list);
+ if (attr_type == NULL)
+ {
+ SWSS_LOG_ERROR("attr SAI_LAG_MEMBER_ATTR_LAG_ID was not passed");
+ return SAI_STATUS_FAILURE;
+ }
+ lag_oid = attr_type->value.oid;
+ sai_object_type_t obj_type = objectTypeQuery(lag_oid);
+
+ if (obj_type != SAI_OBJECT_TYPE_LAG)
+ {
+ SWSS_LOG_ERROR(" SAI_LAG_MEMBER_ATTR_LAG_ID = %s expected to be LAG ID but is: %s",
+ sai_serialize_object_id(lag_oid).c_str(),
+ sai_serialize_object_type(obj_type).c_str());
+ return SAI_STATUS_FAILURE;
+ }
+ bond_if_idx = lag_to_bond_if_idx(lag_oid);
+ SWSS_LOG_NOTICE("bond if index is %d\n",bond_if_idx);
+
+ attr_type = sai_metadata_get_attr_by_id(SAI_LAG_MEMBER_ATTR_PORT_ID, attr_count, attr_list);
+
+ if (attr_type == NULL)
+ {
+ SWSS_LOG_ERROR("attr SAI_LAG_MEMBER_ATTR_PORT_ID was not present\n");
+ return SAI_STATUS_FAILURE;
+ }
+
+ lag_port_oid = attr_type->value.oid;
+ SWSS_LOG_NOTICE("lag port id is %s",sai_serialize_object_id(lag_port_oid).c_str());
+ obj_type = objectTypeQuery(lag_port_oid);
+ if (obj_type != SAI_OBJECT_TYPE_PORT)
+ {
+ SWSS_LOG_NOTICE("SAI_BRIDGE_PORT_ATTR_PORT_ID=%s expected to be PORT but is: %s",
+ sai_serialize_object_id(lag_port_oid).c_str(),
+ sai_serialize_object_type(obj_type).c_str());
+ return SAI_STATUS_FAILURE;
+ }
+
+ std::string if_name;
+ bool found = getTapNameFromPortId(lag_port_oid, if_name);
+ const char *hwifname;
+ if (found == true)
+ {
+ hwifname = tap_to_hwif_name(if_name.c_str());
+ SWSS_LOG_NOTICE("hwif name for port is %s",hwifname);
+ }else {
+ SWSS_LOG_NOTICE("No ports found for lag port id :%s",sai_serialize_object_id(lag_port_oid).c_str());
+ return SAI_STATUS_FAILURE;
+ }
+
+ create_bond_member(bond_if_idx, hwifname,is_passive,is_long_timeout);
+ return SAI_STATUS_SUCCESS;
+}
+
+sai_status_t SwitchStateBase::removeLagMember(
+ _In_ sai_object_id_t lag_member_oid)
+{
+ SWSS_LOG_ENTER();
+
+ vpp_remove_lag_member(lag_member_oid);
+
+ auto sid = sai_serialize_object_id(lag_member_oid);
+
+ CHECK_STATUS(remove_internal(SAI_OBJECT_TYPE_LAG_MEMBER, sid));
+
+ return SAI_STATUS_SUCCESS;
+}
+
+sai_status_t SwitchStateBase::vpp_remove_lag_member(
+ _In_ sai_object_id_t lag_member_oid)
+{
+ SWSS_LOG_ENTER();
+
+ sai_attribute_t attr;
+
+ attr.id = SAI_LAG_MEMBER_ATTR_LAG_ID;
+
+ sai_status_t status = get(SAI_OBJECT_TYPE_LAG_MEMBER, lag_member_oid, 1, &attr);
+
+ if (status != SAI_STATUS_SUCCESS)
+ {
+ SWSS_LOG_ERROR("attr SAI_LAG_MEMBER_ATTR_LAG_ID is not present");
+
+ return SAI_STATUS_FAILURE;
+ }
+ sai_object_id_t lag_oid = attr.value.oid;
+
+ sai_object_type_t obj_type = objectTypeQuery(lag_oid);
+
+ if (obj_type != SAI_OBJECT_TYPE_LAG)
+ {
+ SWSS_LOG_ERROR("attr SAI_LAG_MEMBER_ATTR_LAG_ID is not valid");
+ return SAI_STATUS_FAILURE;
+ }
+
+ attr.id = SAI_LAG_MEMBER_ATTR_PORT_ID;
+
+ status = get(SAI_OBJECT_TYPE_LAG_MEMBER, lag_member_oid, 1, &attr);
+
+ if (status != SAI_STATUS_SUCCESS)
+ {
+ SWSS_LOG_ERROR("attr SAI_LAG_MEMBER_ATTR_PORT_ID is not present");
+
+ return SAI_STATUS_FAILURE;
+ }
+ sai_object_id_t port_oid = attr.value.oid;
+
+ obj_type = objectTypeQuery(port_oid);
+
+ if (obj_type != SAI_OBJECT_TYPE_PORT)
+ {
+ SWSS_LOG_ERROR("attr SAI_LAG_MEMBER_ATTR_PORT_ID is not valid");
+ return SAI_STATUS_FAILURE;
+ }
+
+ std::string if_name;
+ bool found = getTapNameFromPortId(port_oid, if_name);
+ const char *lag_member_ifname;
+ if (found == true)
+ {
+ lag_member_ifname = tap_to_hwif_name(if_name.c_str());
+ SWSS_LOG_NOTICE("hwif name for port is %s",lag_member_ifname);
+ } else {
+ SWSS_LOG_NOTICE("No ports found for lag port id :%s",sai_serialize_object_id(port_oid).c_str());
+ return SAI_STATUS_FAILURE;
+ }
+
+ delete_bond_member(lag_member_ifname);
+ return SAI_STATUS_SUCCESS;
+}
diff --git a/platform/saivpp/vpplib/vppxlate/SaiVppXlate.c b/platform/saivpp/vpplib/vppxlate/SaiVppXlate.c
index 8cb2d73..57ca20f 100644
--- a/platform/saivpp/vpplib/vppxlate/SaiVppXlate.c
+++ b/platform/saivpp/vpplib/vppxlate/SaiVppXlate.c
@@ -53,6 +53,9 @@
#include
#include
+#include
+#include
+
/* l2 API inclusion */
#define vl_typedefs
@@ -187,6 +190,28 @@
#include
#undef vl_api_version
+/* BOND API inclusion */
+
+#define vl_typedefs
+#include
+#undef vl_typedefs
+
+#define vl_endianfun
+#include
+#undef vl_endianfun
+
+#define vl_printfun
+#include
+#undef vl_printfun
+
+#define vl_calcsizefun
+#include
+#undef vl_calcsizefun
+
+#define vl_api_version(n, v) static u32 bond_api_version = v;
+#include
+#undef vl_api_version
+
/* memclnt API inclusion */
#define vl_typedefs /* define message structures */
@@ -675,6 +700,49 @@ vl_api_bridge_domain_details_t_handler (vl_api_bridge_domain_details_t *mp)
return;
}
+static void
+vl_api_bond_create_reply_t_handler (vl_api_bond_create_reply_t *msg)
+{
+ set_reply_status(ntohl(msg->retval));
+
+ if (msg->context) {
+ u32 *swif_idx = (u32 *) get_index_ptr(msg->context);
+ *swif_idx = ntohl(msg->sw_if_index);
+ }
+
+ SAIVPP_WARN("bond add %s(%d)", msg->retval ? "failed" : "successful", msg->retval);
+ if (!msg->retval)
+ {
+ uint32_t bond_if_index = ntohl(msg->sw_if_index);
+ SAIVPP_WARN("created bond if index%d", bond_if_index);
+ }
+ //SAIVPP_ERROR("l2 add del reply handler called %s(%d)",msg->retval ? "failed" : "successful", msg->retval);
+
+}
+
+static void
+vl_api_bond_delete_reply_t_handler (vl_api_bond_delete_reply_t *msg)
+{
+ set_reply_status(ntohl(msg->retval));
+
+ SAIVPP_WARN("bond delete %s(%d)", msg->retval ? "failed" : "successful", msg->retval);
+}
+
+static void
+vl_api_bond_add_member_reply_t_handler (vl_api_bond_add_member_reply_t *msg)
+{
+ set_reply_status(ntohl(msg->retval));
+
+ SAIVPP_WARN("bond add member %s(%d)", msg->retval ? "failed" : "successful", msg->retval);
+}
+
+static void
+vl_api_bond_detach_member_reply_t_handler (vl_api_bond_detach_member_reply_t *msg)
+{
+ set_reply_status(ntohl(msg->retval));
+
+ SAIVPP_WARN("bond detach member %s(%d)", msg->retval ? "failed" : "successful", msg->retval);
+}
#define vl_api_get_first_msg_id_reply_t_handler vl_noop_handler
#define vl_api_get_first_msg_id_reply_t_handler_json vl_noop_handler
@@ -686,6 +754,7 @@ vl_api_bridge_domain_details_t_handler (vl_api_bridge_domain_details_t *mp)
static u16 interface_msg_id_base, memclnt_msg_id_base, __plugin_msg_base;
static u16 l2_msg_id_base;
+static u16 bond_msg_id_base;
static void vpp_base_vpe_init(void)
{
@@ -716,6 +785,10 @@ static void vpp_base_vpe_init(void)
#define L2_MSG_ID(id) \
(VL_API_##id + l2_msg_id_base)
+#define BOND_MSG_ID(id) \
+ (VL_API_##id + bond_msg_id_base)
+
+
#define foreach_vpe_ext_api_reply_msg \
_(INTERFACE_MSG_ID(SW_INTERFACE_DETAILS), sw_interface_details) \
_(INTERFACE_MSG_ID(CREATE_LOOPBACK_INSTANCE_REPLY), create_loopback_instance_reply) \
@@ -739,7 +812,11 @@ static void vpp_base_vpe_init(void)
_(L2_MSG_ID(BRIDGE_DOMAIN_DETAILS), bridge_domain_details) \
_(L2_MSG_ID(BVI_CREATE_REPLY), bvi_create_reply) \
_(L2_MSG_ID(BVI_DELETE_REPLY), bvi_delete_reply) \
- _(L2_MSG_ID(BRIDGE_FLAGS_REPLY), bridge_flags_reply)
+ _(L2_MSG_ID(BRIDGE_FLAGS_REPLY), bridge_flags_reply) \
+ _(BOND_MSG_ID(BOND_CREATE_REPLY), bond_create_reply) \
+ _(BOND_MSG_ID(BOND_DELETE_REPLY), bond_delete_reply) \
+ _(BOND_MSG_ID(BOND_ADD_MEMBER_REPLY), bond_add_member_reply) \
+ _(BOND_MSG_ID(BOND_DETACH_MEMBER_REPLY), bond_detach_member_reply)
static u16 interface_msg_id_base, ip_msg_id_base, ip_nbr_msg_id_base, lcp_msg_id_base, memclnt_msg_id_base, __plugin_msg_base;
static u16 acl_msg_id_base;
@@ -864,6 +941,10 @@ static void get_base_msg_id()
//SAIVPP_ERROR("DELME: l2_msg_id_base %s msg_base_lookup_name:%s l2_api_version:%08x\n", l2_msg_id_base,msg_base_lookup_name,l2_api_version);
//printf("DELME: New change added l2_msg_id_base %s\n", l2_msg_id_base);
+ msg_base_lookup_name = format (0, "bond_%08x%c", bond_api_version, 0);
+ bond_msg_id_base = vl_client_get_first_plugin_msg_id ((char *) msg_base_lookup_name);
+ SAIVPP_WARN("BALA: bond_msg_id_base is %d",bond_msg_id_base);
+ assert(bond_msg_id_base != (u16) ~0);
memclnt_msg_id_base = 0;
}
@@ -1011,6 +1092,20 @@ static u32 get_swif_idx (vat_main_t *vam, const char *ifname)
return ((u32) -1);
}
+static const char * get_swif_name (vat_main_t *vam, const u32 swif_idx)
+{
+ hash_pair_t *p;
+ u8 *name;
+ u32 value;
+
+ hash_foreach_pair (p, vam->sw_if_index_by_interface_name, ({
+ name = (u8 *) (p->key);
+ value = (u32) p->value[0];
+ if (value == swif_idx) return name;
+ }));
+ return NULL;
+}
+
static int config_lcp_hostif (vat_main_t *vam,
vl_api_interface_index_t if_idx,
const char *hostif_name,
@@ -2252,3 +2347,160 @@ int set_bridge_domain_flags(uint32_t bd_id, vpp_bd_flags_t flag, bool enable)
return ret;
}
+
+int create_bond_interface(uint32_t bond_id, uint32_t mode, uint32_t lb, uint32_t *swif_idx)
+{
+ vat_main_t *vam = &vat_main;
+ vl_api_bond_create_t * mp;
+ int ret;
+
+
+ SAIVPP_WARN("Creating bd interface: \n");
+ VPP_LOCK();
+
+ __plugin_msg_base = bond_msg_id_base;
+
+ M (BOND_CREATE, mp);
+
+ mp->id = htonl(bond_id);
+ mp->mode = htonl(mode);
+ mp->lb = htonl(lb);
+ mp->numa_only = false;
+ mp->use_custom_mac = false;
+ mp->context = store_ptr(swif_idx);
+
+ S (mp);
+
+ W (ret);
+
+ VPP_UNLOCK();
+
+ return ret;
+}
+
+int delete_bond_interface(const char *hwif_name)
+{
+ vat_main_t *vam = &vat_main;
+ vl_api_bond_delete_t * mp;
+ int ret;
+
+
+ SAIVPP_WARN("Removing bond interface: \n");
+ VPP_LOCK();
+
+ __plugin_msg_base = bond_msg_id_base;
+
+
+ M (BOND_DELETE, mp);
+
+ if (hwif_name) {
+ u32 idx;
+
+ idx = get_swif_idx(vam, hwif_name);
+ if (idx != (u32) -1) {
+ mp->sw_if_index = htonl(idx);
+ } else {
+ SAIVPP_ERROR("Unable to get sw_index for %s\n", hwif_name);
+ VPP_UNLOCK();
+ return -EINVAL;
+ }
+ } else {
+ VPP_UNLOCK();
+ return -EINVAL;
+ }
+
+ S (mp);
+
+ W (ret);
+
+ VPP_UNLOCK();
+
+ return ret;
+}
+int create_bond_member(uint32_t bond_sw_if_index, const char *hwif_name, bool is_passive, bool is_long_timeout)
+{
+ vat_main_t *vam = &vat_main;
+ vl_api_bond_add_member_t * mp;
+ int ret;
+
+
+ SAIVPP_WARN("Adding member to bond interface: \n");
+ VPP_LOCK();
+
+ __plugin_msg_base = bond_msg_id_base;
+
+
+ M (BOND_ADD_MEMBER, mp);
+
+ if (hwif_name) {
+ u32 idx;
+
+ idx = get_swif_idx(vam, hwif_name);
+ if (idx != (u32) -1) {
+ mp->sw_if_index = htonl(idx);
+ } else {
+ SAIVPP_ERROR("Unable to get sw_index for %s\n", hwif_name);
+ VPP_UNLOCK();
+ return -EINVAL;
+ }
+ } else {
+ VPP_UNLOCK();
+ return -EINVAL;
+ }
+ mp->bond_sw_if_index = htonl(bond_sw_if_index);
+ mp->is_passive = is_passive;
+ mp->is_long_timeout = is_long_timeout;
+
+ S (mp);
+
+ W (ret);
+
+ VPP_UNLOCK();
+
+ return ret;
+}
+
+const char * vpp_get_swif_name (const u32 swif_idx)
+{
+ vat_main_t *vam = &vat_main;
+ return get_swif_name(vam, swif_idx);
+}
+
+
+int delete_bond_member(const char * hwif_name)
+{
+ vat_main_t *vam = &vat_main;
+ vl_api_bond_detach_member_t *mp;
+ int ret;
+
+ VPP_LOCK();
+
+ __plugin_msg_base = bond_msg_id_base;
+
+ M (BOND_DETACH_MEMBER, mp);
+
+ if (hwif_name) {
+ u32 idx;
+
+ idx = get_swif_idx(vam, hwif_name);
+ if (idx != (u32) -1) {
+ mp->sw_if_index = htonl(idx);
+ } else {
+ SAIVPP_ERROR("Unable to get sw_index for %s\n", hwif_name);
+ VPP_UNLOCK();
+ return -EINVAL;
+ }
+ } else {
+ VPP_UNLOCK();
+ return -EINVAL;
+ }
+
+ S (mp);
+
+ W (ret);
+
+ VPP_UNLOCK();
+
+ return ret;
+}
+
diff --git a/platform/saivpp/vpplib/vppxlate/SaiVppXlate.h b/platform/saivpp/vpplib/vppxlate/SaiVppXlate.h
index 1a2daf5..0dc5220 100644
--- a/platform/saivpp/vpplib/vppxlate/SaiVppXlate.h
+++ b/platform/saivpp/vpplib/vppxlate/SaiVppXlate.h
@@ -156,7 +156,23 @@ typedef enum {
VPP_BD_FLAG_ARP_UFWD = 32,
} vpp_bd_flags_t;
+typedef enum {
+ VPP_BOND_API_MODE_ROUND_ROBIN = 1,
+ VPP_BOND_API_MODE_ACTIVE_BACKUP = 2,
+ VPP_BOND_API_MODE_XOR = 3,
+ VPP_BOND_API_MODE_BROADCAST = 4,
+ VPP_BOND_API_MODE_LACP = 5,
+} vpp_bond_mode;
+
+typedef enum {
+ VPP_BOND_API_LB_ALGO_L2 = 0,
+ VPP_BOND_API_LB_ALGO_L34 = 1,
+ VPP_BOND_API_LB_ALGO_L23 = 2,
+ VPP_BOND_API_LB_ALGO_RR = 3,
+ VPP_BOND_API_LB_ALGO_BC = 4,
+ VPP_BOND_API_LB_ALGO_AB = 5,
+} vpp_bond_lb_algo;
extern vpp_event_info_t * vpp_ev_dequeue();
extern void vpp_ev_free(vpp_event_info_t *evp);
@@ -200,6 +216,11 @@ typedef enum {
extern int create_bvi_interface(uint8_t *mac_address, uint32_t instance);
extern int delete_bvi_interface(const char *hwif_name);
extern int set_bridge_domain_flags(uint32_t bd_id, vpp_bd_flags_t flag, bool enable);
+ extern int create_bond_interface(uint32_t bond_id, uint32_t mode, uint32_t lb, uint32_t *swif_idx);
+ extern int delete_bond_interface(const char *hwif_name);
+ extern int create_bond_member(uint32_t bond_sw_if_index, const char *hwif_name, bool is_passive, bool is_long_timeout);
+ extern int delete_bond_member(const char * hwif_name);
+ extern const char * vpp_get_swif_name(const uint32_t swif_idx);
#ifdef __cplusplus
}