前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【重识云原生】第四章云网络4.9.6节——linux switchdev技术

【重识云原生】第四章云网络4.9.6节——linux switchdev技术

作者头像
江中散人_Jun
发布于 2022-09-16 02:28:07
发布于 2022-09-16 02:28:07
2.3K0
举报

1 Switchdev简介

1.1 云网络发展趋势

        云网络发展早期,很多厂商的虚拟化网路方案基于内核模块来实现,这时的带宽通常从千兆到万兆,一般情况下还能够满足要求(SDWAN厂商华夏创新的网络加速就是在内核的PREROUTING上做的,性能还可以)。再后来,进入到25G时代了,基于内核的一些实现已经不能满足业务对网络吞吐的性能要求了,大约在2013~2018左右,很多厂商转向用DPDK实现,着实火了一段时间。到现在逐渐进入100G时代,会发现,无论大厂小厂,都逐渐开始转向智能网卡,网络特性offload到硬件,基本是当前和今后一段时间的主流。

1.2 switchdev介绍

        通常情况下,交换芯片厂商会提供用户态软件开发工具包(SDK)来实现与硬件的接口。要用交换芯片设计一个交换机或路由器产品,设备商需要开发一个网络操作系统(NOS)或者移植像SONiC一样的开源产品。这并不能够有效地满足不断变化的市场需求。为了满足网络扩展和应用需求的增长,硬件设备商需要不断开发新技术和新协议,这就导致变更的成本高昂,大部分情况下客户都会抱怨响应速度太慢。

        Switchdev的出现就帮助厂商解决了这一难题,因为它利用大家熟知的Linux开源框架,用户利用Linux环境和工具就可以打破厂商的禁锢,这种灵活性和自由度可以更好地满足客户的需求。

        如下图所示,Switchdev位于Linux内核层,它可以将内核的数据转发平面卸载到交换机的ASIC芯片上。通过这种方式,就可以用标准开放的Linux接口取代专有的SDK和NOS接口。Switchdev还规划了一个统一的接口,简化了集成、配置和支持的过程。与SONiC等NOS相比,Switchdev驱动的网络系统更加轻量级。

        智能网卡厂商也可以利用开放的Linux原生接口来实现对硬件的控制。Switchdev可以用来管理服务器端的网卡,配置物理端口和虚拟端口之间的通信。

1.3 DENT操作系统

        Switchdev项目由Linux内核(具体是netdev)托管,这是Linux基金会旗下的一个开源项目社区。随着Linux内核的变化,无论是增加新的功能还是关键问题的修复,通过社区就可以确保Switchdev基础架构持续向前演进。 Linux有众多的应用程序来实现各种网络协议,主要的愿景就是让这些协议能够利用到交换机的硬件能力,或者说利用到交换芯片来卸载流量处理,这样就不会浪费通用CPU资源。为了将基础级的Switchdev转化为白盒设备所需的全面商用级NOS,Linux基金会正在围绕Switchdev建立一个应用生态系统DENT,创始成员包括亚马逊和一些网络硬件厂商。

        DENT操作系统架构图 DENT是基于Ubuntu的Linux发行版,它封装了交换机硬件(风扇、温度传感器、ASIC等)的驱动程序以及开源的FRRouting路由协议套件,其中包括BGP、IS-IS、LDP、OSPF、PIM和RIP的协议守护进程。FRRouting软件使用Linux netlink API对Linux内核的数据包转发进行编程,在硬件交换机平台上,数据包转发由switchdev驱动卸载到ASIC进行线速转发。 DENT采用Linux作为网络操作系统的一个主要优势是,用于配置、管理和监控Linux服务器的工具也可以用来管理网络交换机。此外,DENT虚拟机的运行方式与在物理交换机上运行的DENT完全相同,这样就可以保证配置在进入生产网络之前在虚拟环境中得到充分验证。

1.4 应用案例

        本案例利用开源的Host sFlow代理从Linux主机收集标准的sFlow遥测数据。在基于switchdev的网络交换机上,通过标准的Linux API就可以收集硬件计数器数据用于监控网络接口。Host sFlow 代理也支持 Linux psample 和 drop_monitor API,可以提供数据流和丢包的可视性。在硬件交换机上,switchdev驱动程序将测量交由交换机ASIC完成,从而可以实现数据包线速转发的可视性。 在基于DENT OS的交换机上安装Host sFlow代理,交换芯片通过标准sFlow硬件模块可以将网络遥测数据流传输到sFlow采集器,例如sFlow-RT,从而可以获得网络自动化所需的实时全网性能视图。

流量采集案例图

1.5 Switchdev成功的关键

        目前高端网络设备市场已经开始普及白盒产品,中低端商用交换机和路由器等细分市场如果想要打开白盒交换机的想象空间,就必须有一套开放、灵活和标准的解决方案,Switchdev的目标就是为客户提供一个全新的、简化的网络设备开发环境。 通过采用Switchdev作为开源基础架构框架,就可以利用到开放的Linux工具,设备厂商省去开发专有NOS或网管系统的商务成本,同时减少整合商业交换芯片所需的繁琐开发流程。统一的Linux界面也降低了客户的使用成本,简化了学习曲线。智能网卡采用Switchdev可以方便地与数据中心或网络编排系统(OpenStackKubernetes、XCloud等)集成。 开发Switchdev需要包括Linux内核、驱动和应用方面的相关知识,软件工程师要有底层网络和嵌入式软件开发能力,包括对所选交换芯片SDK的了解和平台集成经验。芯片和设备厂商在为其产品开发Switchdev驱动时,在遵循开源社区的开发原则同时,建议将相应产品的Switchdev驱动向Linux内核提交。因为Switchdev尚在发展中,设备厂商在为产品适配Switchdev时,相关平台代码以及移植问题上传到开源社区,就可以确保在未来的Linux发行版中得到支持。

2 架构

        switchdev框架是从Linux 4.0引入的,它代表一类拥有“交换”能力芯片的多网口设备的抽象。其中每一个网口就是一个port,在switchdev框架中被注册成一个net_device。除此之外,内核中自带了一个rocker driver,演示了一个实际的设备驱动的实现。

        利用Switchdev,除了常见的Linux内核数据面能够卸载到硬件,也可以直接将流表注入到设备中,从而指导设备直接进行数据包交换,如mellanox的一些智能网卡的做法。采用了硬件交换模块的Linux BOX和原来的截然不同了,它更像是一个高端的专业网络设备,类似Cisco那样的。它看起来就是下面的样子:

3 相关源码

3.1 rocker dirver

        它是内核中自带了一个rocker driver,演示了一个实际的设备驱动的实现,最先支持 switchdev 的就是是 QEMU 的 Rocker 软件交换机。后来 Mellanox 和 Broadcom 等公司均提供了支持 switchdev 的交换机器。它就是一个pci dirver,对接了switchdev框架将kernel数据面下发的模拟的硬件。

static struct pci_driver rocker_pci_driver = {

    .name = rocker_driver_name,

    .id_table = rocker_pci_id_table,

    .probe = rocker_probe,

    .remove = rocker_remove,

};

        Rocker 是一个模拟网络交换机平台,旨在加速内核网络交换机驱动程序模型的开发。 Rocker 有两个部分:一个带有 PCI 主机接口的 62 端口交换机芯片的 Qemu 仿真和一个 Linux 设备驱动程序。 目标是模拟数据中心/企业中使用的当代网络交换机 ASIC 的功能,以便社区可以在内核中开发交换机设备驱动程序接口。 最初的目标功能是 L2 桥接功能卸载和 L3 路由功能卸载。 在这两种情况下,转发(数据)平面都被卸载到交换机设备,但控制和管理平面仍保留在 Linux 中。 L2overL3 隧道、L2 绑定、ACL 支持和基于流的网络等其他功能正在计划中或正在进行中。

        根据官方的说法,Rocker 背后的动机是加速开发用于网络交换机的 Linux 内核设备驱动程序模型,在没有供应商提供的开源驱动程序的情况下,Rocker 被创建为网络交换机设备的仿真,其功能集接近于现实世界的供应商交换机 ASIC。使用 Rocker 设备,我们可以创建设备驱动程序来开发和测试 switchdev 驱动程序模型,而无需依赖供应商的 SDK。期望一旦 switchdev 达到一定的成熟度,供应商或社区提供的用于现实世界 ASIC 的设备驱动程序将会出现,并且对 Rocker 的需求将随着时间的推移而减少。也就是说是一个演示性质的实现,为大家开发支持switchdev的设备驱动提供参考。

3.2 代码 (kernel 5.15)

        从第一张图,我们可以看到能够通过switchdev框架下发的硬件的转发面信息可能有下面一些:

  • port信息,包括接口的属性、状态等;
  • 二层fdb表项,包括bridge fdb、vxlan fdb表项等;
  • 三层转发表项;
  • 通过tc下发的流控表项,openflow流表也是可以通过tc下发的。 下面简单看看一下这部分内核代码,简单过了一下,可能有错,仅供参考……_。

1、二层fdb表项

  • bridge fdb表项: 无论是静态配置fdb表项或者是动态学习fdb表项,内核创建fdb表项成功后,会调用fdb_notify 函数,如:

void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, const unsigned char *addr, u16 vid, unsigned long flags)

{

    struct net_bridge_fdb_entry *fdb; /* some users want to always flood. */

    if (hold_time(br) == 0)

        return;

    fdb = fdb_find_rcu(&br->fdb_hash_tbl, addr, vid);

    if (likely(fdb)) {

        /* attempt to update an entry for a local interface */

        if (unlikely(test_bit(BR_FDB_LOCAL, &fdb->flags))) {

            if (net_ratelimit())

                  br_warn(br, "received packet on %s with own address as source address (addr:%pM, vlan:%u)\n", source->dev->name, addr, vid);

        } else {

            unsigned long now = jiffies;

            bool fdb_modified = false;

            if (now != fdb->updated) {

                fdb->updated = now;

                fdb_modified = __fdb_mark_active(fdb);

            }

            /* fastpath: update of existing entry */

            if (unlikely(source != READ_ONCE(fdb->dst) && !test_bit(BR_FDB_STICKY, &fdb->flags))) {

                br_switchdev_fdb_notify(br, fdb, RTM_DELNEIGH);

                WRITE_ONCE(fdb->dst, source);

                fdb_modified = true;

                /* Take over HW learned entry */

                if (unlikely(test_bit(BR_FDB_ADDED_BY_EXT_LEARN, &fdb->flags)))

                    clear_bit(BR_FDB_ADDED_BY_EXT_LEARN, &fdb->flags);

            }

            if (unlikely(test_bit(BR_FDB_ADDED_BY_USER, &flags)))

                set_bit(BR_FDB_ADDED_BY_USER, &fdb->flags);

            if (unlikely(fdb_modified)) {

                trace_br_fdb_update(br, source, addr, vid, flags);

                fdb_notify(br, fdb, RTM_NEWNEIGH, true);

            }

        }

    } else {

        spin_lock(&br->hash_lock);

        fdb = fdb_create(br, source, addr, vid, flags);

        if (fdb) {

            trace_br_fdb_update(br, source, addr, vid, flags);

            fdb_notify(br, fdb, RTM_NEWNEIGH, true);

        }

        /* else we lose race and someone else inserts * it first, don't bother updating */         spin_unlock(&br->hash_lock);

    }

}

        fdb_notify做两个事情,

  1. 调用br_switchdev_fdb_notify 进switchdev框架,offload fdb表项到硬件;
  2. 通过netilink 发布fdb表项变化事件(RTNLGRP_NEIGH),用户态内核态都可以监听以获取fdb数据变化。

static void fdb_notify(struct net_bridge *br, const struct net_bridge_fdb_entry *fdb, int type, bool swdev_notify) {

        struct net *net = dev_net(br->dev);

        struct sk_buff *skb;

        int err = -ENOBUFS;

        if (swdev_notify)

            br_switchdev_fdb_notify(br, fdb, type);

        skb = nlmsg_new(fdb_nlmsg_size(), GFP_ATOMIC);

        if (skb == NULL)

             goto errout;

        err = fdb_fill_info(skb, br, fdb, 0, 0, type, 0);

        if (err < 0) {

            /* -EMSGSIZE implies BUG in fdb_nlmsg_size() */

            WARN_ON(err == -EMSGSIZE);

            kfree_skb(skb);

            goto errout;

        }

        rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);

        return;

errout:

        rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);

}

void br_switchdev_fdb_notify(struct net_bridge *br, const struct net_bridge_fdb_entry *fdb, int type) {

        const struct net_bridge_port *dst = READ_ONCE(fdb->dst);

        struct switchdev_notifier_fdb_info info = {

            .addr = fdb->key.addr.addr,

            .vid = fdb->key.vlan_id,

            .added_by_user = test_bit(BR_FDB_ADDED_BY_USER, &fdb->flags),

            .is_local = test_bit(BR_FDB_LOCAL, &fdb->flags),

            .offloaded = test_bit(BR_FDB_OFFLOADED, &fdb->flags),

        };

        struct net_device *dev = (!dst || info.is_local) ? br->dev : dst->dev;

        switch (type) {

            case RTM_DELNEIGH:

                call_switchdev_notifiers(SWITCHDEV_FDB_DEL_TO_DEVICE, dev, &info.info, NULL);

                break;

            case RTM_NEWNEIGH:

                call_switchdev_notifiers(SWITCHDEV_FDB_ADD_TO_DEVICE, dev, &info.info, NULL);

                break;

        }

}

        br_switchdev_fdb_notify函数通过内核通知链,发出 fdb 添加到设备(SWITCHDEV_FDB_ADD_TO_DEVICE)、从设备删除(SWITCHDEV_FDB_DEL_TO_DEVICE)通知,如果设备支持switchdev框架,设备驱动中会注册并相应这两个通知的内核通知链,假如还是rocker dirver。

        Rocker 在 rocker_switchdev_event 中处理这两个通知,通过queue_work 最终调用 rocker_switchdev_event_work 函数处理这两个通知,调用rocker的wops->port_obj_fdb_add 添加fdb,挂载的是ofdpa_port_obj_fdb_add 函数,一直往下看,在ofdpa_flow_tbl_bridge 函数中将fdb数据封装成ofdpa_flow_tbl_entry,统一成了流表数据,其实rocker中,无论是fdb 还是 fib,或者是tc下发的转发规则包括ovs流表,最终都转化为ofdpa_flow_tbl_entry 。

        最后的流程如下,ofdpa_cmd_flow_tbl_add 将ofdpa_flow_tbl_entry 再加工成 struct rocker_desc_info *desc_info,是qemu virio driver识别的数据了,再执行rocker_desc_head_set(rocker, &rocker->cmd_ring, desc_info); 放置到驱动的ring中等待取走。

static int ofdpa_flow_tbl_add(struct ofdpa_port *ofdpa_port, int flags, struct ofdpa_flow_tbl_entry *match) {

        struct ofdpa *ofdpa = ofdpa_port->ofdpa;

        struct ofdpa_flow_tbl_entry *found;

        size_t key_len = match->key_len ? match->key_len : sizeof(found->key);

        unsigned long lock_flags;

        match->key_crc32 = crc32(~0, &match->key, key_len);

        spin_lock_irqsave(&ofdpa->flow_tbl_lock, lock_flags);

        found = ofdpa_flow_tbl_find(ofdpa, match);

        if (found) {

            match->cookie = found->cookie;

            hash_del(&found->entry);

            kfree(found);

            found = match;

            found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_FLOW_MOD;

        } else {

            found = match;

            found->cookie = ofdpa->flow_tbl_next_cookie++;

            found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_FLOW_ADD;

        }

        hash_add(ofdpa->flow_tbl, &found->entry, found->key_crc32);

        spin_unlock_irqrestore(&ofdpa->flow_tbl_lock, lock_flags);

        return rocker_cmd_exec(ofdpa_port->rocker_port, ofdpa_flags_nowait(flags), ofdpa_cmd_flow_tbl_add, found, NULL, NULL);

}

int rocker_cmd_exec(struct rocker_port *rocker_port, bool nowait,

                rocker_cmd_prep_cb_t prepare, void *prepare_priv,

                rocker_cmd_proc_cb_t process, void *process_priv)

{

        struct rocker *rocker = rocker_port->rocker;

        struct rocker_desc_info *desc_info;

        struct rocker_wait *wait;

        unsigned long lock_flags;

        int err;

        spin_lock_irqsave(&rocker->cmd_ring_lock, lock_flags);

        desc_info = rocker_desc_head_get(&rocker->cmd_ring);

        if (!desc_info) {

            spin_unlock_irqrestore(&rocker->cmd_ring_lock, lock_flags);

            return -EAGAIN;

        }

        wait = rocker_desc_cookie_ptr_get(desc_info);

        rocker_wait_init(wait);

        wait->nowait = nowait;

        err = prepare(rocker_port, desc_info, prepare_priv);

        if (err) {

            spin_unlock_irqrestore(&rocker->cmd_ring_lock, lock_flags);

            return err;

        }

        rocker_desc_head_set(rocker, &rocker->cmd_ring, desc_info);

        spin_unlock_irqrestore(&rocker->cmd_ring_lock, lock_flags);

        if (nowait)

            return 0;

        if (!rocker_wait_event_timeout(wait, HZ / 10))

            return -EIO;

        err = rocker_desc_err(desc_info);

        if (err)

            return err;

        if (process)

            err = process(rocker_port, desc_info, process_priv);

        rocker_desc_gen_clear(desc_info);

        return err;

}

2、三层转发表项

  • 内核添加fib表项,调用 fib_table_insert 函数,添加成功后,发出一个 FIB_EVENT_ENTRY_ADD 类型的notifier call,注册过内核通知链的模块将处理该通知。

fib_table_insert:

        call_fib_entry_notifiers(net, FIB_EVENT_ENTRY_ADD, key, plen, fi, new_fa->fa_tos, cfg->fc_type, tb->tb_id, cfg->fc_nlflags);

  • rocker驱动中注册了这个事件,还有其他路有事件都在这里处理。

static int rocker_router_fib_event(struct notifier_block *nb, unsigned long event, void *ptr) {

        struct rocker *rocker = container_of(nb, struct rocker, fib_nb);

        struct fib_entry_notifier_info *fen_info = ptr;

        int err;

        switch (event) {

            case FIB_EVENT_ENTRY_ADD:

                err = rocker_world_fib4_add(rocker, fen_info);

                if (err)

                    rocker_world_fib4_abort(rocker);

                else break;

            case FIB_EVENT_ENTRY_DEL:

                rocker_world_fib4_del(rocker, fen_info);

                break;

            case FIB_EVENT_RULE_ADD:

            /* fall through */

            case FIB_EVENT_RULE_DEL:

                rocker_world_fib4_abort(rocker);

                break;

        }

        return NOTIFY_DONE;

}

static int rocker_world_fib4_add(struct rocker *rocker, const struct fib_entry_notifier_info *fen_info) {

        struct rocker_world_ops *wops = rocker->wops;

        if (!wops->fib4_add)

            return 0;

        return wops->fib4_add(rocker, fen_info);

}

ops 挂的 ofdpa_fib4_add 函数。

struct rocker_world_ops rocker_ofdpa_ops = {

        .kind = "ofdpa",

        .priv_size = sizeof(struct ofdpa),

        .port_priv_size = sizeof(struct ofdpa_port),

        .mode = ROCKER_PORT_MODE_OF_DPA,

        .init = ofdpa_init,

        .fini = ofdpa_fini,

        .port_pre_init = ofdpa_port_pre_init,

        .port_init = ofdpa_port_init,

        .port_fini = ofdpa_port_fini,

        .port_open = ofdpa_port_open,

        .port_stop = ofdpa_port_stop,

        .port_attr_stp_state_set = ofdpa_port_attr_stp_state_set,

        .port_attr_bridge_flags_set = ofdpa_port_attr_bridge_flags_set,

        .port_attr_bridge_flags_get = ofdpa_port_attr_bridge_flags_get,

        .port_attr_bridge_ageing_time_set = ofdpa_port_attr_bridge_ageing_time_set,

        .port_obj_vlan_add = ofdpa_port_obj_vlan_add,

        .port_obj_vlan_del = ofdpa_port_obj_vlan_del,

        .port_obj_vlan_dump = ofdpa_port_obj_vlan_dump,

        .port_obj_fdb_add = ofdpa_port_obj_fdb_add,

        .port_obj_fdb_del = ofdpa_port_obj_fdb_del,

        .port_obj_fdb_dump = ofdpa_port_obj_fdb_dump,

        .port_master_linked = ofdpa_port_master_linked,

        .port_master_unlinked = ofdpa_port_master_unlinked,

        .port_neigh_update = ofdpa_port_neigh_update,

        .port_neigh_destroy = ofdpa_port_neigh_destroy,

        .port_ev_mac_vlan_seen = ofdpa_port_ev_mac_vlan_seen,

        .fib4_add = ofdpa_fib4_add,

        .fib4_del = ofdpa_fib4_del,

        .fib4_abort = ofdpa_fib4_abort,

};

        最终调用ofdpa_flow_tbl_add,这个函数中调用rocker_cmd_exec函数先将ofdpa_flow_tbl_entry 转化为rocker_desc_info( ofdpa_cmd_flow_tbl_add 函数完成),再将rocker_desc_info set到驱动的 dma ring中等待硬件读取,流程结束。

static int ofdpa_flow_tbl_add(struct ofdpa_port *ofdpa_port, struct switchdev_trans *trans,

                int flags, struct ofdpa_flow_tbl_entry *match)

{

        struct ofdpa *ofdpa = ofdpa_port->ofdpa;

        struct ofdpa_flow_tbl_entry *found;

        size_t key_len = match->key_len ? match->key_len : sizeof(found->key);

        unsigned long lock_flags;

        match->key_crc32 = crc32(~0, &match->key, key_len);

        spin_lock_irqsave(&ofdpa->flow_tbl_lock, lock_flags);

        found = ofdpa_flow_tbl_find(ofdpa, match);

        if (found) {

            match->cookie = found->cookie;

            if (!switchdev_trans_ph_prepare(trans))

                hash_del(&found->entry);

            ofdpa_kfree(trans, found);

            found = match;

            found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_FLOW_MOD;

        } else {

                found = match;

                found->cookie = ofdpa->flow_tbl_next_cookie++;

                found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_FLOW_ADD;

        }

        if (!switchdev_trans_ph_prepare(trans))

            hash_add(ofdpa->flow_tbl, &found->entry, found->key_crc32);

        spin_unlock_irqrestore(&ofdpa->flow_tbl_lock, lock_flags);

        if (!switchdev_trans_ph_prepare(trans))

            return rocker_cmd_exec(ofdpa_port->rocker_port, ofdpa_flags_nowait(flags), ofdpa_cmd_flow_tbl_add, found, NULL, NULL);

        return 0;

}

int rocker_cmd_exec(struct rocker_port *rocker_port, bool nowait,

                rocker_cmd_prep_cb_t prepare, void *prepare_priv,

                rocker_cmd_proc_cb_t process, void *process_priv)

{

        struct rocker *rocker = rocker_port->rocker;

        struct rocker_desc_info *desc_info;

        struct rocker_wait *wait;

        unsigned long lock_flags;

        int err;

        spin_lock_irqsave(&rocker->cmd_ring_lock, lock_flags);

        desc_info = rocker_desc_head_get(&rocker->cmd_ring);

        if (!desc_info) {

            spin_unlock_irqrestore(&rocker->cmd_ring_lock, lock_flags);

            return -EAGAIN;

        }

        wait = rocker_desc_cookie_ptr_get(desc_info);

        rocker_wait_init(wait);

        wait->nowait = nowait;

        err = prepare(rocker_port, desc_info, prepare_priv);

        if (err) {

            spin_unlock_irqrestore(&rocker->cmd_ring_lock, lock_flags);

            return err;

        }

        rocker_desc_head_set(rocker, &rocker->cmd_ring, desc_info);

        spin_unlock_irqrestore(&rocker->cmd_ring_lock, lock_flags);

        if (nowait)

            return 0;

        if (!rocker_wait_event_timeout(wait, HZ / 10))

            return -EIO;

        err = rocker_desc_err(desc_info);

        if (err)

            return err;

        if (process)

            err = process(rocker_port, desc_info, process_priv);

        rocker_desc_gen_clear(desc_info);

        return err;

}

3、port 属性、状态

        也是通过内核通知链完成的,同上,入口 switchdev_port_obj_add,调用的地方不多,可以自己看。

参考链接

linux switchdev 介绍 & 源码 - 简书

Switchdev:释放开源Linux的网络力量_mob604756f52321的技术博客_51CTO博客

Linux switchdev | Houmin

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-07-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【重识云原生】第四章云网络4.9.1节——网络卸载加速技术综述
网络offload主要是指将原本在内核网络协议栈中进行的IP分片、TCP分段、重组、checksum校验等操作,转移到网卡硬件中进行,CPU的发包路径更短,消耗更低,提高处理性能。
江中散人_Jun
2022/07/12
3.3K0
【重识云原生】第四章云网络4.9.1节——网络卸载加速技术综述
【重识云原生】第四章云网络4.8.3.1节——Open vSwitch简介
        在过去十几年中,虚拟化已经改变了应用、数据、服务的实现部署方式。服务器的虚拟化给数据中心网络带来了根本性的变化。在传统的数据中心网络架构基础上,出现了一个新的、位于物理服务器内的接入层。这个新的接入层包含的设备是运行在x86服务器中的vSwitch,而这些vSwitch连接着一个服务器内的多个workload(包括容器和虚机)。
江中散人_Jun
2022/07/12
5.4K0
【重识云原生】第四章云网络4.8.3.1节——Open vSwitch简介
【重识云原生】第四章云网络4.8.3.2节——Open vSwitch工作原理详解
        先看下OVS整体架构,用户空间主要组件有数据库服务ovsdb-server和守护进程ovs-vswitchd。kernel中是datapath内核模块。最上面的Controller表示OpenFlow控制器,控制器与OVS是通过OpenFlow协议进行连接,控制器不一定位于OVS主机上,下面分别介绍图中各组件。
江中散人_Jun
2022/07/12
2.1K0
【重识云原生】第四章云网络4.8.3.2节——Open vSwitch工作原理详解
【重识云原生】第四章云网络4.8.4节——OpenStack与SDN的集成
        OpenStack自己官方的网络项目是Neutron,Neutron有着自己的一套网络实现方案:基于linux namespace,构建一个个相对独立的虚拟网络功能单元。通过这些网络功能单元提供OpenStack所需要的网络服务。Neutron在自己的实现之外,也考虑了第三方功能的兼容,例如2层的功能被抽象到了ML2的mechanism driver,各个网络功能被抽象到了对应的service plugin。第三方SDN只需要实现相应的mechanism driver和service plugins,就能接入到OpenStack Neutron。进而在整个OpenStack环境下使用。Neutron的架构如下图所示:
江中散人_Jun
2022/07/12
1.4K0
【重识云原生】第四章云网络4.8.4节——OpenStack与SDN的集成
【重识云原生】第四章云网络4.7.1节——网络虚拟化与卸载加速技术的演进简述
        近几年,软件定义网络(Software Define Network,SDN)技术的发展与成熟,使得网络虚拟化可以不再基于物理网络设备实现,大大扩展了网络虚拟化的“边界”。需要强调的是,SDN 不等于网络虚拟化,只是SDN 这种技术非常适合实现网络虚拟化。
江中散人_Jun
2022/06/27
1.4K0
【重识云原生】第四章云网络4.7.1节——网络虚拟化与卸载加速技术的演进简述
【重识云原生】第四章云网络4.8.2.2节——OpenFlow协议详解
        OpenFlow协议是基于网络中“流”的概念设计的南向接口协议。在OpenFlow引入了“流”的概念之后,控制器可以根据某次通信中“流”的第一个数据分组的特征,使用OpenFlow协议提供的接口对数据平面设备部署策略——流表,而这次通信的后续流量则按照相应流表在硬件层次上进行匹配、转发,从而实现了灵活的网络转发策略。
江中散人_Jun
2022/07/12
2.5K0
【重识云原生】第四章云网络4.8.2.2节——OpenFlow协议详解
OVS BUG撸码回忆录 •上篇
本文作者 / yogazhao 爱自然科学,赞叹于大师级码农高超的艺术境界;爱生命科学,诚服于古圣先贤的天地气象。 可能大多数瓜农都对《艺伎回忆录》比较熟悉,作为一个IT界的码农,当然也有自己类似的经历,该文分为上篇和下篇,此篇为《OVS BUG撸码回忆录•上篇》 回忆录缘起 以前为排查ovs的某个bug,无奈撸了把相关内核流程。当时因为调用链太多,脑袋栈溢出,处理不过来,所以临时用txt比较零散的记录了下关键点,做完了就丢了。后面想起来,无奈用everything找了好久才找到, 再读之,发现忘了很
腾讯云TStack
2019/07/19
1.4K0
OVS BUG撸码回忆录 •上篇
【重识云原生】第四章云网络4.9.3.1节——DPDK技术综述
        数据平面开发套件(DPDK [1]  ,Data Plane Development Kit)是由6WIND,Intel等多家公司开发,主要基于Linux系统运行,用于快速数据包处理的函数库与驱动集合,可以极大提高数据处理性能和吞吐量,提高数据平面应用程序的工作效率。
江中散人_Jun
2022/09/08
1.6K0
【重识云原生】第四章云网络4.9.3.1节——DPDK技术综述
【重识云原生】第四章云网络4.8.2.3节——OpenFlow运行机制
        要了解OpenFlow信道的建立过程,首先需要了解OpenFlow协议目前支持的三种报文类型:
江中散人_Jun
2022/07/12
1.8K0
【重识云原生】第四章云网络4.8.2.3节——OpenFlow运行机制
【重识云原生】第四章云网络4.8.1节——SDN总述
        SDN起源于2006年斯坦福大学的Clean Slate研究课题。2009年,Mckeown教授正式提出了SDN概念。
江中散人_Jun
2022/07/12
1.4K0
【重识云原生】第四章云网络4.8.1节——SDN总述
【重识云原生】第四章云网络4.3.10.3节——VXLAN隧道机制
        从上图中可以发现,VXLAN网络中出现了以下传统数据中心网络中没有的新元素:
江中散人_Jun
2022/06/14
8440
【重识云原生】第四章云网络4.3.10.3节——VXLAN隧道机制
Intel E810网卡芯片架构简介及以太内核驱动初始化源码分析
E810 基于 100G 以太网控制器核心模块,该模块用于多种英特尔产品。图 1-1 说明了控制器核心逻辑与组成完整 E810 设备的 I/O 和支持功能之间的关系
晓兵
2024/12/14
4870
Intel E810网卡芯片架构简介及以太内核驱动初始化源码分析
聊聊 Linux 上软件实现的“交换机” - Bridge!
Linux 中的 veth 是一对儿能互相连接、互相通信的虚拟网卡。通过使用它,我们可以让 Docker 容器和母机通信,或者是在两个 Docker 容器中进行交流。参见《轻松理解 Docker 网络虚拟化基础之 veth 设备!》。
开发内功修炼
2022/03/24
1.5K1
聊聊 Linux 上软件实现的“交换机” - Bridge!
【重识云原生】第四章云网络4.3.10.2节——VXLAN Overlay网络方案设计
        VXLAN 本质上是一种重叠封装技术,它创建了一个覆盖在现有物理网络基础架构之上的虚拟网络。使用underlay IP网络,并在其上构建灵活的二层overlay逻辑网络。通过覆盖,任何第 2 层连接都可以跨越第 3 层网络。
江中散人_Jun
2022/06/12
1.2K0
【重识云原生】第四章云网络4.3.10.2节——VXLAN Overlay网络方案设计
【重识云原生】第四章云网络4.3.2节——VLAN技术
        VLAN(Virtual Local Area Network)即虚拟局域网,是将一个物理的LAN在逻辑上划分成多个广播域的通信技术。VLAN内的主机间可以直接通信,而VLAN间不能直接互通,从而将广播报文限制在一个VLAN内。
江中散人_Jun
2022/05/25
9560
【重识云原生】第四章云网络4.3.2节——VLAN技术
【重识云原生】第四章云网络4.8.2.1节——OpenFlow概述
        转发和控制分离是SDN网络的本质特点之一 。在SDN网络架构中,控制平面与转发平面分离,网络的管理和状态在逻辑上集中到一起,底层的网络基础从应用中独立出来,由此,网络获得前所未有的可编程、可控制和自动化能力。这使用户可以很容易根据业务需求,建立高度可扩展的弹性网络。要实现SDN网络的转控分离架构,就需要在SDN控制器与数据转发层之间建立一个通信接口标准。
江中散人_Jun
2022/07/12
9981
【重识云原生】第四章云网络4.8.2.1节——OpenFlow概述
【重识云原生】第四章云网络4.7.3节——Vhost-net方案
        virtio是一种I/O半虚拟化解决方案,是一套通用I/O设备虚拟化的程序,是对半虚拟化Hypervisior中的一组通用I/O设备的抽象。virtio分为前端和后端,一个backend组件和一个frontend组件。backend组件是virtio接口的host端,frontend组件是virtio的guest端。
江中散人_Jun
2022/06/27
2.5K0
【重识云原生】第四章云网络4.7.3节——Vhost-net方案
【重识云原生】第四章云网络4.8.6节——Dragonflow
        DragonFlow是华为以色列技术团队2014年提出的,2015年开始提交代码,目前已经成为OpenStack的孵化项目。DragonFlow最初的目标是通过可插拔、无状态、轻量级的SDN控制器来实现分布式路由,它的提出是为了解决DVR(Distributed Virtual Router,分布式虚拟路由技术)中存在的一些问题,主要是DVR会造成计算节点上资源和性能的一些损耗。
江中散人_Jun
2022/09/08
1.1K0
【重识云原生】第四章云网络4.3.10节——VXLAN技术
        VXLAN (Virtual eXtensible LAN,可扩展虚拟局域网络) 是一种Internet 标准重叠网络虚拟化技术,它提供了一种在 IP(第 3 层)网络上封装以太网(第 2 层)帧的方法,这一概念通常被称为“隧道”。VXLAN采用MAC in UDP(User Datagram Protocol)封装方式,是NVO3(Network Virtualization over Layer 3)中的一种网络虚拟化技术。
江中散人_Jun
2022/06/12
1.4K0
【重识云原生】第四章云网络4.3.10节——VXLAN技术
开放网络设备关键使能技术
网络设备(如交换机)一般由思科、华为、华三等网络设备商基于Broadcom、Intel、Marvell等网络芯片商的芯片方案进行研发测试并交付最终客户。过去相当长一段时间,芯片厂商为了保护自己的知识产权,通过SDK的形式开放操作芯片的API接口供网络设备商进行设备开发,且获得SDK需要和芯片厂商签署SLA、NDA等保密协议,某种程度上对网络设备商进行了“锁定”。网络设备商基于芯片厂家特有的SDK开发出的网络设备,传统linux的ip、ethtool、brctl等命令统统失效,留给用户的是专用的命令行或网络管理工具,这在某种程度上对网络设备的用户进行了“锁定”。
SDNLAB
2021/04/29
1.1K0
推荐阅读
相关推荐
【重识云原生】第四章云网络4.9.1节——网络卸载加速技术综述
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档