1.patch端口
ovs的patch端口,用于连接两个网桥,命令如下
ovs-vsctl add-port br10 patch3 -- set interface patch3 type=patch options:peer=patch4
ovs-vsctl add-port br12 patch4 -- set interface patch4 type=patch options:peer=patch3
patch类型端口,不会将其添加到datapath中,在port_add函数中有个判断,如果是patch类型的端口就直接return了。所以通过 ovs-appctl dpctl/show 是看不到patch端口的
通过patch端口连接的两个ovs bridge的datapath_type必须相同。
static int
port_add(struct ofproto *ofproto_, struct netdev *netdev)
{
struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_);
const char *devname = netdev_get_name(netdev);
char namebuf[NETDEV_VPORT_NAME_BUFSIZE];
const char *dp_port_name;
//如果是patch类型端口,则返回。不会将其添加到datapath中
if (netdev_vport_is_patch(netdev)) {
sset_add(&ofproto->ghost_ports, netdev_get_name(netdev));
return 0;
}
dp_port_name = netdev_vport_get_dpif_port(netdev, namebuf, sizeof namebuf);
if (!dpif_port_exists(ofproto->backer->dpif, dp_port_name)) {
odp_port_t port_no = ODPP_NONE;
int error;
将端口添加到datapath中
error = dpif_port_add(ofproto->backer->dpif, netdev, &port_no);
if (error) {
return error;
}
if (netdev_get_tunnel_config(netdev)) {
simap_put(&ofproto->backer->tnl_backers,
dp_port_name, odp_to_u32(port_no));
}
}
if (netdev_get_tunnel_config(netdev)) {
sset_add(&ofproto->ghost_ports, devname);
} else {
sset_add(&ofproto->ports, devname);
}
}
patch端口的数据转发,会在peer端口关联的bridge上查找流表,最终会将流表和action安装到datapath中
static void
compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
const struct xlate_bond_recirc *xr, bool check_stp)
//如果patch端口有peer,则发送给peer
if (xport->peer) {
apply_nested_clone_actions(ctx, xport, xport->peer);
return;
}
//如果patch端口没有peer
if (xport->is_tunnel) {
...
} else {
//因为xport没有peer,所以xport->odp_port 为ODPP_NONE。
//比如通过patch端口连接两个不同类型datapath的网桥,patch端口的peer就是空的,所以也不能互相转发。
odp_port = xport->odp_port;
out_port = odp_port;
}
if (out_port != ODPP_NONE) {
}
static void
apply_nested_clone_actions(struct xlate_ctx *ctx, const struct xport *in_dev,
struct xport *out_dev)
//in_port 修改成出端口的id
flow->in_port.ofp_port = out_dev->ofp_port;
//临时设置成peer端口所在的桥
ctx->xbridge = out_dev->xbridge;
//查找peer端口所在的桥的openflow table,相当于peer端口收到报文的处理
xlate_table_action(ctx, flow->in_port.ofp_port, 0, true, true,false);
//查找 openflow table
rule = rule_dpif_lookup_from_table();
xlate_recursively(ctx, rule, table_id <= old_table_id);
actions = rule_get_actions(&rule->up);
//执行action
do_xlate_actions(actions->ofpacts, actions->ofpacts_len, ctx);
//恢复出端口所在桥
ctx->xbridge = in_dev->xbridge;
2.创建网桥和patch口
ovs-vsctl add-br br10 -- set bridge br10 datapath_type=netdev
ovs-vsctl add-br br12 -- set bridge br12 datapath_type=netdev
ovs-vsctl add-port br10 patch3 -- set interface patch3 type=patch options:peer=patch4 ovs-vsctl add-port br12 patch4 -- set interface patch4 type=patch options:peer=patch3
ovs-vsctl add-br br11 -- set bridge br11 datapath_type=system
ovs-vsctl add-port br10 patch1 -- set interface patch1 type=patch options:peer=patch2 ovs-vsctl add-port br11 patch2 -- set interface patch2 type=patch options:peer=patch1
查询ovs端口信息
ovs-vsctl show
e436075d-bffe-4cce-8cab-91cf99f0a4b2
Bridge "br10"
Port "patch3"
Interface "patch3"
type: patch
options: {peer="patch4"}
Port "patch1"
Interface "patch1"
type: patch
options: {peer="patch2"}
Port "br10"
Interface "br10"
type: internal
Bridge "br11"
Port "br11"
Interface "br11"
type: internal
Port "patch2"
Interface "patch2"
type: patch
options: {peer="patch1"}
Bridge "br12"
Port "patch4"
Interface "patch4"
type: patch
options: {peer="patch3"}
Port "br12"
Interface "br12"
type: internal
//查看datapath信息
//可看到有两个datapath:netdev和system,并且datapath中不包含任何patch端口
ovs-appctl dpctl/show
netdev@ovs-netdev:
lookups: hit:2022051 missed:25 lost:0
flows: 1
port 0: ovs-netdev (tap)
port 1: br10 (tap)
port 2: enp129s0f0
port 3: br12 (tap)
system@ovs-system:
lookups: hit:0 missed:0 lost:0
flows: 0
masks: hit:0 total:1 hit/pkt:0.00
port 0: ovs-system (internal)
port 1: br11 (internal)
patch端口的特点:
1.patch端口只存在网桥上,datapath中不会存在
2. 如果出端口为patch端口,则相当于其peer设备收到报文,在peer设备所在网桥查找openflow流表进行转发
3. 不同类型datapath的网桥不能通过patch端口相连接
3.datapath类型
ovs的datapath类型只有两种:system或者netdev
system类型位于kernel的datapath,报文的收发都在内核态进行
netdev可以位于用户态,支持两种类型的端口: non-pmd/pmd,前者可以是linux系统上绑定在kernel driver的物理网卡,也可以是tap等虚拟网卡,后者需要dpdk的支持,所以需要在编译时,就指定dpdk提供的lib,其使用dpdk的pmd线程处理网卡,可以是物理网卡,也可以是vhost-user虚拟网卡。
a. 每种datapath可以支持多个网桥,不同datapath类型的网桥不能互通。
b. patch端口只存在于ofproto层面,不会下发到datapath中,所以通过 "ovs-appctl dpctl/show" 命令是看不到patch端口的。
c. kernel datapath在openvswitch.ko模块中直接调用网卡驱动进行收发包。
userspace datapath中,对于non-pmd端口,使用af_socket或者read/write /dev/net/tun实现收发包,对于pmd类型端口,使用其dpdk driver在用户态实现收发包。