AT_BANNER([system-inteface])

dnl add a veth interface to br0, then delete and re-create
dnl the veth interface with the same name in the system
AT_SETUP([interface - add delete add same interface])

OVS_TRAFFIC_VSWITCHD_START()

AT_CHECK([ip link add ovs-veth0 type veth peer name ovs-veth1])
on_exit 'ip link del ovs-veth0'

AT_CHECK([ovs-vsctl add-port br0 ovs-veth0])

AT_CHECK([ip link del ovs-veth0])
AT_CHECK([ip link add ovs-veth0 type veth peer name ovs-veth1])

AT_CHECK([ovs-vsctl del-port br0 ovs-veth0])

OVS_TRAFFIC_VSWITCHD_STOP(["dnl
/could not open network device ovs-veth0/d
/cannot get .*STP status on nonexistent port/d
/ethtool command .*on network device ovs-veth0 failed/d
/error receiving .*ovs-veth0/d
/ovs-veth0: removing policing failed/d"])

AT_CLEANUP

dnl add a p1-0 interface to br-p1, then add a route to br-p1 and stop the OvS
dnl instance. Confirm br-p1 interface has been deleted from the system.
AT_SETUP([interface - add route to br and verify clean-up])

OVS_TRAFFIC_VSWITCHD_START()

HWADDR_BRP1=aa:55:00:00:00:01

dnl Create tap port to later add to br-p1
AT_CHECK([ip tuntap add name p1-0 mode tap])
AT_CHECK([ip link set p1-0 up])
on_exit 'ip link del p1-0'

AT_CHECK([
    ovs-vsctl add-br br-p1 -- \
        set bridge br-p1 datapath_type=netdev fail-mode=standalone other-config:hwaddr=$HWADDR_BRP1

    ovs-vsctl add-port br-p1 p1-0

    ovs-ofctl del-flows br-p1
], [0])

AT_CHECK([
    ip addr add 10.0.0.1/24 dev br-p1
    ip link set br-p1 up
], [0], [stdout])

AT_CHECK([
    ovs-appctl ovs/route/add 10.0.0.0/24 br-p1
    ovs-appctl tnl/arp/set br-p1 10.0.0.1 $HWADDR_BRP1
], [0], [stdout])

OVS_TRAFFIC_VSWITCHD_STOP
AT_CHECK([
    ip link show br-p1], [1],
    [stdout], [Device "br-p1" does not exist.]
)
AT_CLEANUP

AT_SETUP([interface - datapath ports garbage collection])
OVS_CHECK_GENEVE()
OVS_TRAFFIC_VSWITCHD_START()

dnl Not relevant for userspace datapath.
AT_SKIP_IF([! ovs-appctl dpctl/show | grep -q ovs-system])

AT_CHECK([ovs-vsctl add-port br0 tunnel_port dnl
            -- set Interface tunnel_port dnl
                   type=geneve options:remote_ip=flow options:key=123])

AT_CHECK([ip link add ovs-veth0 type veth peer name ovs-veth1])
on_exit 'ip link del ovs-veth0'

AT_CHECK([ovs-vsctl add-port br0 ovs-veth0])

OVS_WAIT_UNTIL([ip link show | grep -q " genev_sys_[[0-9]]*: .* ovs-system "])

dnl Store the output of ip link for geneve port to compare ifindex later.
AT_CHECK([ip link show | grep " genev_sys_[[0-9]]*: .* ovs-system " > geneve.0])

AT_CHECK([ovs-appctl dpctl/show | grep port], [0], [dnl
  port 0: ovs-system (internal)
  port 1: br0 (internal)
  port 2: genev_sys_6081 (geneve: packet_type=ptap)
  port 3: ovs-veth0
])

OVS_APP_EXIT_AND_WAIT_BY_TARGET([ovs-vswitchd], [ovs-vswitchd.pid])

dnl Check that geneve backing interface is still in the datapath.
AT_CHECK([ip link show | grep " genev_sys_[[0-9]]*: .* ovs-system " | diff -u - geneve.0])

dnl Remove the veth port from the database while ovs-vswitchd is down.
AT_CHECK([ovs-vsctl --no-wait del-port ovs-veth0])

dnl Check that it is still tied to the OVS datapath.
AT_CHECK([ip link show ovs-veth0 | grep -q ovs-system])

dnl Bring ovs-vswitchd back up.
AT_CHECK([ovs-vswitchd --detach --no-chdir --pidfile --log-file -vdpif:dbg],
         [0], [], [stderr])

dnl Wait for the veth port to be removed from the datapath.
OVS_WAIT_WHILE([ip link show ovs-veth0 | grep -q ovs-system])

AT_CHECK([ovs-appctl dpctl/show | grep port], [0], [dnl
  port 0: ovs-system (internal)
  port 1: br0 (internal)
  port 2: genev_sys_6081 (geneve: packet_type=ptap)
])

dnl Check that geneve backing interface is still in the datapath and it wasn't
dnl re-created, i.e. the ifindex is the same.
AT_CHECK([ip link show | grep " genev_sys_[[0-9]]*: .* ovs-system " | diff -u - geneve.0])

OVS_TRAFFIC_VSWITCHD_STOP
AT_CLEANUP

AT_SETUP([interface - datapath port rename])
OVS_TRAFFIC_VSWITCHD_START()

dnl Not relevant for userspace datapath.
AT_SKIP_IF([! ovs-appctl dpctl/show | grep -q ovs-system])

AT_CHECK([ip link add ovs-veth0 type veth peer name ovs-veth1])
dnl We will rename ovs-veth0, so removing the peer on exit.
on_exit 'ip link del ovs-veth1'

AT_CHECK([ovs-vsctl add-port br0 ovs-veth0])

OVS_WAIT_UNTIL([ip link show | grep -q "ovs-veth0.* ovs-system "])

AT_CHECK([ovs-appctl dpctl/show | grep port], [0], [dnl
  port 0: ovs-system (internal)
  port 1: br0 (internal)
  port 2: ovs-veth0
])

dnl Rename the interface while attached to OVS.
AT_CHECK([ip l set ovs-veth0 name ovs-new-port])

dnl Wait for the port to be detached from the OVS datapath.
OVS_WAIT_UNTIL([ip link show | grep "ovs-new-port" | grep -v "ovs-system"])

dnl Check that database indicates the error.
AT_CHECK([ovs-vsctl get interface ovs-veth0 error], [0], [dnl
"could not open network device ovs-veth0 (No such device)"
])

dnl Check that the port is no longer in the datapath.
AT_CHECK([ovs-appctl dpctl/show | grep port], [0], [dnl
  port 0: ovs-system (internal)
  port 1: br0 (internal)
])

dnl Rename the interface back and check that it is in use again.
AT_CHECK([ip l set ovs-new-port name ovs-veth0])

OVS_WAIT_UNTIL([ip link show | grep -q "ovs-veth0.* ovs-system "])

AT_CHECK([ovs-vsctl get interface ovs-veth0 error], [0], [dnl
[[]]
])

AT_CHECK([ovs-appctl dpctl/show | grep port], [0], [dnl
  port 0: ovs-system (internal)
  port 1: br0 (internal)
  port 2: ovs-veth0
])

OVS_TRAFFIC_VSWITCHD_STOP(["
  /could not open network device ovs-veth0 (No such device)/d
"])
AT_CLEANUP

AT_SETUP([interface - current speed])
AT_SKIP_IF([test $HAVE_ETHTOOL = "no"])
OVS_TRAFFIC_VSWITCHD_START()

AT_CHECK([ip tuntap add tap0 mode tap])
on_exit 'ip tuntap del tap0 mode tap'

AT_CHECK([ip link set dev tap0 address aa:55:aa:55:00:01])
AT_CHECK([ethtool -s tap0 speed 50000 duplex full])
AT_CHECK([ip link set dev tap0 up])

AT_CHECK([ovs-vsctl add-port br0 tap0 -- set int tap0 type=tap])

AT_CHECK([ovs-ofctl -O OpenFlow15 -vwarn dump-ports-desc br0 tap0], [0], [stdout])
AT_CHECK([strip_xids < stdout], [0], [dnl
OFPST_PORT_DESC reply (OF1.5):
 1(tap0): addr:aa:55:aa:55:00:01
     config:     0
     state:      LIVE
     current:    OTHER COPPER
     speed: 50000 Mbps now, 0 Mbps max
])

AT_CHECK([ovs-vsctl get interface tap0 link_speed], [0], [dnl
50000000000
])

AT_CHECK([ovs-vsctl get interface tap0 duplex], [0], [dnl
full
])

AT_CHECK([ip link set dev tap0 down])
AT_CHECK([ethtool -s tap0 duplex half])
AT_CHECK([ip link set dev tap0 up])

AT_CHECK([ovs-vsctl get interface tap0 duplex], [0], [dnl
half
])

OVS_TRAFFIC_VSWITCHD_STOP
AT_CLEANUP
