Commit f94ecbc9 authored by Aaron Conole's avatar Aaron Conole Committed by Jakub Kicinski

selftests: openvswitch: Support explicit tunnel port creation.

The OVS module can operate in conjunction with various types of
tunnel ports.  These are created as either explicit tunnel vport
types, OR by creating a tunnel interface which acts as an anchor
for the lightweight tunnel support.

This patch adds the ability to add tunnel ports to an OVS
datapath for testing various scenarios with tunnel ports.  With
this addition, the vswitch "plumbing" will at least be able to
push packets around using the tunnel vports.  Future patches
will add support for setting required tunnel metadata for lwts
in the datapath.  The end goal will be to push packets via these
tunnels, and will be used in an upcoming commit for testing the
path MTU.
Reviewed-by: default avatarSimon Horman <horms@kernel.org>
Tested-by: default avatarSimon Horman <horms@kernel.org>
Signed-off-by: default avatarAaron Conole <aconole@redhat.com>
Link: https://patch.msgid.link/20240625172245.233874-2-aconole@redhat.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 346a03e5
...@@ -10,6 +10,7 @@ import ipaddress ...@@ -10,6 +10,7 @@ import ipaddress
import logging import logging
import multiprocessing import multiprocessing
import re import re
import socket
import struct import struct
import sys import sys
import time import time
...@@ -29,6 +30,7 @@ try: ...@@ -29,6 +30,7 @@ try:
from pyroute2.netlink.exceptions import NetlinkError from pyroute2.netlink.exceptions import NetlinkError
from pyroute2.netlink.generic import GenericNetlinkSocket from pyroute2.netlink.generic import GenericNetlinkSocket
import pyroute2 import pyroute2
import pyroute2.iproute
except ModuleNotFoundError: except ModuleNotFoundError:
print("Need to install the python pyroute2 package >= 0.6.") print("Need to install the python pyroute2 package >= 0.6.")
...@@ -1617,7 +1619,7 @@ class OvsVport(GenericNetlinkSocket): ...@@ -1617,7 +1619,7 @@ class OvsVport(GenericNetlinkSocket):
("OVS_VPORT_ATTR_PORT_NO", "uint32"), ("OVS_VPORT_ATTR_PORT_NO", "uint32"),
("OVS_VPORT_ATTR_TYPE", "uint32"), ("OVS_VPORT_ATTR_TYPE", "uint32"),
("OVS_VPORT_ATTR_NAME", "asciiz"), ("OVS_VPORT_ATTR_NAME", "asciiz"),
("OVS_VPORT_ATTR_OPTIONS", "none"), ("OVS_VPORT_ATTR_OPTIONS", "vportopts"),
("OVS_VPORT_ATTR_UPCALL_PID", "array(uint32)"), ("OVS_VPORT_ATTR_UPCALL_PID", "array(uint32)"),
("OVS_VPORT_ATTR_STATS", "vportstats"), ("OVS_VPORT_ATTR_STATS", "vportstats"),
("OVS_VPORT_ATTR_PAD", "none"), ("OVS_VPORT_ATTR_PAD", "none"),
...@@ -1625,6 +1627,13 @@ class OvsVport(GenericNetlinkSocket): ...@@ -1625,6 +1627,13 @@ class OvsVport(GenericNetlinkSocket):
("OVS_VPORT_ATTR_NETNSID", "uint32"), ("OVS_VPORT_ATTR_NETNSID", "uint32"),
) )
class vportopts(nla):
nla_map = (
("OVS_TUNNEL_ATTR_UNSPEC", "none"),
("OVS_TUNNEL_ATTR_DST_PORT", "uint16"),
("OVS_TUNNEL_ATTR_EXTENSION", "none"),
)
class vportstats(nla): class vportstats(nla):
fields = ( fields = (
("rx_packets", "=Q"), ("rx_packets", "=Q"),
...@@ -1693,7 +1702,7 @@ class OvsVport(GenericNetlinkSocket): ...@@ -1693,7 +1702,7 @@ class OvsVport(GenericNetlinkSocket):
raise ne raise ne
return reply return reply
def attach(self, dpindex, vport_ifname, ptype): def attach(self, dpindex, vport_ifname, ptype, dport, lwt):
msg = OvsVport.ovs_vport_msg() msg = OvsVport.ovs_vport_msg()
msg["cmd"] = OVS_VPORT_CMD_NEW msg["cmd"] = OVS_VPORT_CMD_NEW
...@@ -1702,12 +1711,43 @@ class OvsVport(GenericNetlinkSocket): ...@@ -1702,12 +1711,43 @@ class OvsVport(GenericNetlinkSocket):
msg["dpifindex"] = dpindex msg["dpifindex"] = dpindex
port_type = OvsVport.str_to_type(ptype) port_type = OvsVport.str_to_type(ptype)
msg["attrs"].append(["OVS_VPORT_ATTR_TYPE", port_type])
msg["attrs"].append(["OVS_VPORT_ATTR_NAME", vport_ifname]) msg["attrs"].append(["OVS_VPORT_ATTR_NAME", vport_ifname])
msg["attrs"].append( msg["attrs"].append(
["OVS_VPORT_ATTR_UPCALL_PID", [self.upcall_packet.epid]] ["OVS_VPORT_ATTR_UPCALL_PID", [self.upcall_packet.epid]]
) )
TUNNEL_DEFAULTS = [("geneve", 6081),
("vxlan", 4789)]
for tnl in TUNNEL_DEFAULTS:
if ptype == tnl[0]:
if not dport:
dport = tnl[1]
if not lwt:
vportopt = OvsVport.ovs_vport_msg.vportopts()
vportopt["attrs"].append(
["OVS_TUNNEL_ATTR_DST_PORT", socket.htons(dport)]
)
msg["attrs"].append(
["OVS_VPORT_ATTR_OPTIONS", vportopt]
)
else:
port_type = OvsVport.OVS_VPORT_TYPE_NETDEV
ipr = pyroute2.iproute.IPRoute()
if tnl[0] == "geneve":
ipr.link("add", ifname=vport_ifname, kind=tnl[0],
geneve_port=dport,
geneve_collect_metadata=True,
geneve_udp_zero_csum6_rx=1)
elif tnl[0] == "vxlan":
ipr.link("add", ifname=vport_ifname, kind=tnl[0],
vxlan_learning=0, vxlan_collect_metadata=1,
vxlan_udp_zero_csum6_rx=1, vxlan_port=dport)
break
msg["attrs"].append(["OVS_VPORT_ATTR_TYPE", port_type])
try: try:
reply = self.nlm_request( reply = self.nlm_request(
msg, msg_type=self.prid, msg_flags=NLM_F_REQUEST | NLM_F_ACK msg, msg_type=self.prid, msg_flags=NLM_F_REQUEST | NLM_F_ACK
...@@ -2053,12 +2093,19 @@ def print_ovsdp_full(dp_lookup_rep, ifindex, ndb=NDB(), vpl=OvsVport()): ...@@ -2053,12 +2093,19 @@ def print_ovsdp_full(dp_lookup_rep, ifindex, ndb=NDB(), vpl=OvsVport()):
for iface in ndb.interfaces: for iface in ndb.interfaces:
rep = vpl.info(iface.ifname, ifindex) rep = vpl.info(iface.ifname, ifindex)
if rep is not None: if rep is not None:
opts = ""
vpo = rep.get_attr("OVS_VPORT_ATTR_OPTIONS")
if vpo:
dpo = vpo.get_attr("OVS_TUNNEL_ATTR_DST_PORT")
if dpo:
opts += " tnl-dport:%s" % socket.ntohs(dpo)
print( print(
" port %d: %s (%s)" " port %d: %s (%s%s)"
% ( % (
rep.get_attr("OVS_VPORT_ATTR_PORT_NO"), rep.get_attr("OVS_VPORT_ATTR_PORT_NO"),
rep.get_attr("OVS_VPORT_ATTR_NAME"), rep.get_attr("OVS_VPORT_ATTR_NAME"),
OvsVport.type_to_str(rep.get_attr("OVS_VPORT_ATTR_TYPE")), OvsVport.type_to_str(rep.get_attr("OVS_VPORT_ATTR_TYPE")),
opts,
) )
) )
...@@ -2120,12 +2167,30 @@ def main(argv): ...@@ -2120,12 +2167,30 @@ def main(argv):
"--ptype", "--ptype",
type=str, type=str,
default="netdev", default="netdev",
choices=["netdev", "internal"], choices=["netdev", "internal", "geneve", "vxlan"],
help="Interface type (default netdev)", help="Interface type (default netdev)",
) )
addifcmd.add_argument(
"-p",
"--dport",
type=int,
default=0,
help="Destination port (0 for default)"
)
addifcmd.add_argument(
"-l",
"--lwt",
type=bool,
default=True,
help="Use LWT infrastructure instead of vport (default true)."
)
delifcmd = subparsers.add_parser("del-if") delifcmd = subparsers.add_parser("del-if")
delifcmd.add_argument("dpname", help="Datapath Name") delifcmd.add_argument("dpname", help="Datapath Name")
delifcmd.add_argument("delif", help="Interface name for adding") delifcmd.add_argument("delif", help="Interface name for adding")
delifcmd.add_argument("-d",
"--dellink",
type=bool, default=False,
help="Delete the link as well.")
dumpflcmd = subparsers.add_parser("dump-flows") dumpflcmd = subparsers.add_parser("dump-flows")
dumpflcmd.add_argument("dumpdp", help="Datapath Name") dumpflcmd.add_argument("dumpdp", help="Datapath Name")
...@@ -2186,7 +2251,8 @@ def main(argv): ...@@ -2186,7 +2251,8 @@ def main(argv):
print("DP '%s' not found." % args.dpname) print("DP '%s' not found." % args.dpname)
return 1 return 1
dpindex = rep["dpifindex"] dpindex = rep["dpifindex"]
rep = ovsvp.attach(rep["dpifindex"], args.addif, args.ptype) rep = ovsvp.attach(rep["dpifindex"], args.addif, args.ptype,
args.dport, args.lwt)
msg = "vport '%s'" % args.addif msg = "vport '%s'" % args.addif
if rep and rep["header"]["error"] is None: if rep and rep["header"]["error"] is None:
msg += " added." msg += " added."
...@@ -2207,6 +2273,9 @@ def main(argv): ...@@ -2207,6 +2273,9 @@ def main(argv):
msg += " removed." msg += " removed."
else: else:
msg += " failed to remove." msg += " failed to remove."
if args.dellink:
ipr = pyroute2.iproute.IPRoute()
ipr.link("del", index=ipr.link_lookup(ifname=args.delif)[0])
elif hasattr(args, "dumpdp"): elif hasattr(args, "dumpdp"):
rep = ovsdp.info(args.dumpdp, 0) rep = ovsdp.info(args.dumpdp, 0)
if rep is None: if rep is None:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment