# mkdir ovs3.5
# cd ovs3.5/
# wget 
# dnf install -y wget
# wget http://download-01.beak-001.prod.iad2.dc.redhat.com/brewroot/vol/rhel-9/packages/openvswitch3.5/3.5.0/32.el9fdp/noarch/openvswitch3.5-test-3.5.0-32.el9fdp.noarch.rpm
# wget http://download-01.beak-001.prod.iad2.dc.redhat.com/brewroot/vol/rhel-9/packages/openvswitch3.5/3.5.0/32.el9fdp/x86_64/openvswitch3.5-3.5.0-32.el9fdp.x86_64.rpm
# wget http://download-01.beak-001.prod.iad2.dc.redhat.com/brewroot/vol/rhel-9/packages/openvswitch3.5/3.5.0/32.el9fdp/x86_64/python3-openvswitch3.5-3.5.0-32.el9fdp.x86_64.rpm
# wget http://download.devel.redhat.com/brewroot/vol/rhel-9/packages/ovn24.09/24.09.2/26.el9fdp/x86_64/ovn24.09-24.09.2-26.el9fdp.x86_64.rpm
# wget http://download-01.beak-001.prod.iad2.dc.redhat.com/brewroot/vol/rhel-9/packages/openvswitch-selinux-extra-policy/1.0/38.el9fdp/noarch/openvswitch-selinux-extra-policy-1.0-38.el9fdp.noarch.rpm
# wget http://download-01.beak-001.prod.iad2.dc.redhat.com/brewroot/vol/rhel-9/packages/ovn24.09/24.09.2/26.el9fdp/x86_64/ovn24.09-central-24.09.2-26.el9fdp.x86_64.rpm
# wget http://download-01.beak-001.prod.iad2.dc.redhat.com/brewroot/vol/rhel-9/packages/ovn24.09/24.09.2/26.el9fdp/x86_64/ovn24.09-host-24.09.2-26.el9fdp.x86_64.rpm
# wget http://download-01.beak-001.prod.iad2.dc.redhat.com/brewroot/vol/rhel-9/packages/ovn24.09/24.09.2/26.el9fdp/x86_64/ovn24.09-vtep-24.09.2-26.el9fdp.x86_64.rpm
# dnf install ./*.rpm

# Init ovs and ovn service
modprobe openvswitch
systemctl status openvswitch
systemctl restart openvswitch
systemctl restart ovn-northd
systemctl stop ovn-controller

# Create ovs bridge
ovs-vsctl --if-exists del-br br-int
ovs-vsctl --if-exists del-br br-ext
ovs-vsctl add-br br-int
ovs-vsctl add-br br-ext
ovs-ofctl add-flow br-ext action=normal

# set br-int external ID and config
ovs-vsctl     \
-- set Open_vSwitch . external-ids:system-id=hv1     \
-- set Open_vSwitch . external-ids:ovn-remote=unix:/var/run/ovn/ovnsb_db.sock     \
-- set Open_vSwitch . external-ids:ovn-encap-type=geneve     \
-- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1     \
-- set bridge br-int fail-mode=secure other-config:disable-in-band=true     \
-- set Open_vSwitch . external-ids:ovn-bridge-mappings=phynet:br-ext

# Start ovn-controller
systemctl start ovn-controller


# Create logical router and switch
ovn-nbctl lr-del lr
ovn-nbctl lr-add lr
ovn-nbctl ls-del internal
ovn-nbctl ls-add internal
ovn-nbctl ls-del public
ovn-nbctl ls-add public
ovn-nbctl show

# Config router and sw port
ovn-nbctl lrp-add lr lr-pub 00:00:01:01:02:03 192.168.1.1/24
ovn-nbctl lsp-add public pub-lr -- set Logical_Switch_Port pub-lr type=router options:router-port=lr-pub addresses=\"00:00:01:01:02:03\"
ovn-nbctl lrp-add lr lr-internal 00:00:01:01:02:04 172.16.1.1/24
ovn-nbctl lsp-add internal internal-lr -- set Logical_Switch_Port internal-lr  type=router options:router-port=lr-internal addresses=\"00:00:01:01:02:04\"
ovn-nbctl lsp-add internal server -- lsp-set-addresses server "f0:00:0f:01:02:03 172.16.1.2"
# config localnet port
ovn-nbctl lsp-add public ln_port -- lsp-set-addresses ln_port unknown -- lsp-set-type ln_port localnet -- lsp-set-options ln_port network_name=phynet

# set router option
ovn-nbctl set logical_router lr options:chassis=hv1

ovs-vsctl --if-exists del-port br-ext veth-client
ovs-vsctl --if-exists del-port br-int veth-server

# Create client NS and interface
modprobe -r veth
ip netns del client
ip netns add client
ip link add client type veth peer name veth-client
ip link set client netns client

ovs-vsctl add-port br-ext veth-client
ip addr add 192.168.1.2/24 dev veth-client
ip link set veth-client up
ip netns exec client ip addr add 192.168.1.2/24 dev client
ip netns exec client ip link set client up
ip netns exec client ip route add default via 192.168.1.1
ip netns exec client ip link set dev client mtu 900

# Create server NS and port
ip netns del server
ip netns add server
ip link add server type veth peer name veth-server
ip link set server netns server
ovs-vsctl add-port br-int veth-server
ovs-vsctl set Interface veth-server external_ids:iface-id=server
ip addr add 172.16.1.2/24 dev veth-server
ip link set veth-server up
ip netns exec server ip addr add 172.16.1.2/24 dev server
ip netns exec server ip link set server up
ip netns exec server ip route add default via 172.16.1.1


# config ovn load-balancer
ovn-nbctl lb-del lb1
ovn-nbctl lb-add lb1 172.16.1.20:4242 172.16.1.2:4242 udp
ovn-nbctl ls-lb-add public lb1
ovn-nbctl --wait=hv sync

# run test
# clean conntrack table
ovs-appctl dpctl/flush-conntrack

# Listen UDP 4242 and Capture the traffic
ip netns exec server nc -l -u 172.16.1.2 4242 > /dev/null &
SERVER_PID=$!
ip netns exec server tcpdump -l -U -i server -vnne 'udp and ip[6:2] > 0 and not ip[6] = 64' -w server.pcap &
TCPDUMP1_PID=$!

##############client side##########################

#create client.py with below contents
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(b"x" * 4000, ("172.16.1.20", 4242))

# run client script
ip netns exec client python3 ./client.py

# Check result
ovs-appctl dpctl/dump-conntrack -m
ovs-appctl dpctl/dump-flows -m
ovn-sbctl --uuid dump-flows public
ovs-ofctl dump-flows br-int table=21

#clean env
# kill $TCPDUMP0_PID $TCPDUMP1_PID $SERVER_PID
