openvswitch 的patch端口与datapath类型

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在用户态实现收发包。

参考链接:https://www.jianshu.com/p/85ebe068c460

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值