網(wǎng)絡(luò)實(shí)踐- vlan與橋接原理

背景信息

因?yàn)楣ぷ餍再|(zhì)的變動(dòng)褐啡,許久不更新文章了。最近在做裸金屬管理的項(xiàng)目鳖昌,因?yàn)橘Y源限制备畦,缺少物理機(jī)低飒,而且物理機(jī)啟動(dòng)太慢,不利于開(kāi)發(fā)懂盐,所以選擇用虛擬機(jī)來(lái)模擬物理機(jī)褥赊。在搭建測(cè)試環(huán)境的過(guò)程中,遇到了一些問(wèn)題莉恼,在解決這些問(wèn)題的過(guò)程中拌喉,有很多網(wǎng)絡(luò)方面的收貨,經(jīng)過(guò)一些思考和閱讀源碼解開(kāi)了心中的很多疑惑俐银。比如下面這些問(wèn)題尿背,你是否想的清楚呢?

  • 將物理網(wǎng)卡添加到linx bridge中捶惜,linux bridge是如何接管物理網(wǎng)卡的呢田藐?
  • 將物理網(wǎng)卡添加到ovs橋中,ovs橋是如何接管物理網(wǎng)卡的呢吱七?
  • 為什么物理網(wǎng)卡不能同時(shí)加入到linux bridge和ovs橋呢汽久?
  • 在linux系統(tǒng)中,為什么不能創(chuàng)建多個(gè)vlan id相同的vlan子接口呢踊餐?
  • 將網(wǎng)卡加入到bond中景醇,又在bond上創(chuàng)建了vlan子接口,流量又是如何轉(zhuǎn)發(fā)的呢吝岭?

資源部署架構(gòu)

部署關(guān)系圖.png

這是在一臺(tái)物理機(jī)部署的很多虛擬機(jī)啊易,其中虛擬機(jī)1颗品、虛擬機(jī)2和裸金屬服務(wù)虛機(jī)是直接在物理機(jī)上使用libvirt啟動(dòng)的虛擬機(jī)帐姻,虛擬機(jī)3忘伞、虛擬機(jī)4、虛擬機(jī)5是通過(guò)kubevirt啟動(dòng)的虛機(jī)微峰,kubevirt使用的網(wǎng)絡(luò)方案是kube-ovn的underlay的方式舷丹,即ovs橋接管bond0網(wǎng)卡,虛擬機(jī)通過(guò)ovs橋蜓肆,直接連到物理網(wǎng)絡(luò)上颜凯。

首先需要介紹一些前置的知識(shí),才能更好的理解這些內(nèi)容仗扬。

  • 裸金屬管理:裸金屬管理的最終目的是 能夠像虛擬機(jī)一樣管理虛擬機(jī)症概,包括裸金屬服務(wù)器的啟停、監(jiān)控早芭、自動(dòng)安裝系統(tǒng)彼城、修改密碼、自動(dòng)擴(kuò)容根分區(qū)等等。裸金屬管理的方案選擇的是使用開(kāi)源的ironic募壕,又因?yàn)閕ronic依賴(lài)于openstack環(huán)境调炬,所以選擇使用bifrost,bifrost是用于自動(dòng)部署ironic服務(wù)舱馅,并使得ironic不依賴(lài)于openstack環(huán)境缰泡。
  • kubevirt : kubevirt是基于kubernetes的輕量虛擬化管理平臺(tái),使得用戶(hù)能夠在kubernetes環(huán)境中同時(shí)使用容器和虛擬機(jī)代嗤。
  • ovs :全稱(chēng)是openvswitch棘钞,簡(jiǎn)單來(lái)說(shuō),就是一個(gè)虛擬的交換機(jī)干毅,通過(guò)sdn接管ovs宜猜,可以實(shí)現(xiàn)很強(qiáng)大的網(wǎng)絡(luò)功能。
  • 虛擬機(jī)模擬物理機(jī):物理機(jī)的自動(dòng)裝機(jī)包括dhcp溶锭、ipmi控制從網(wǎng)絡(luò)啟動(dòng)宝恶、開(kāi)關(guān)機(jī)等符隙,可用使用vbmcd來(lái)模擬ipmi趴捅,通過(guò)這些模擬方案,可以實(shí)現(xiàn)用虛擬機(jī)來(lái)模擬物理機(jī)霹疫,搭建裸金屬管理的開(kāi)發(fā)環(huán)境拱绑。

網(wǎng)絡(luò)邏輯關(guān)系

現(xiàn)在把目光聚集到網(wǎng)絡(luò)層面,看一下各個(gè)網(wǎng)絡(luò)設(shè)備之間的關(guān)系丽蝎。


網(wǎng)絡(luò)設(shè)備關(guān)系圖.png

從類(lèi)別上分猎拨,enp1和enp2屬于物理網(wǎng)卡,vlan子接口和bond0屬于虛擬網(wǎng)絡(luò)設(shè)備屠阻,linux bridge和ovs橋?qū)儆谔摂M交換機(jī)红省。

從主從關(guān)系講,vlan子接口是linux bridge的從設(shè)備国觉,bond0是ovs橋的從設(shè)備吧恃,enp1和enp2是bond0的從設(shè)備。

有幾個(gè)特殊的點(diǎn)麻诀,需要提一下痕寓,vlan子接口并不是bond0的從設(shè)備,這個(gè)后面會(huì)說(shuō)明我的分析蝇闭,bond0的角色既是主設(shè)備呻率,又是從設(shè)備。

網(wǎng)絡(luò)協(xié)議棧

網(wǎng)絡(luò)協(xié)議棧十分復(fù)雜呻引,這里并不會(huì)詳細(xì)分析網(wǎng)絡(luò)協(xié)議棧的實(shí)現(xiàn)礼仗,只是簡(jiǎn)要介紹一個(gè)網(wǎng)絡(luò)協(xié)議棧的處理流程,方便對(duì)于后文的理解。

為了簡(jiǎn)便和擴(kuò)展元践,網(wǎng)絡(luò)進(jìn)行了分層挪丢,就是大家熟悉的二層卢厂、三層乾蓬、四層、七層慎恒。其中任内,二、三融柬、四是在內(nèi)核態(tài)處理的死嗦,七層是在用戶(hù)態(tài)處理的。在內(nèi)核態(tài)處理的這部分就是網(wǎng)絡(luò)協(xié)議棧的核心內(nèi)容粒氧。

已收包為例越除,物理網(wǎng)卡收到包后,進(jìn)行拆包外盯,解析二層的類(lèi)型摘盆,調(diào)用對(duì)應(yīng)的二層的處理函數(shù),二層收到包后饱苟,進(jìn)行拆包孩擂,解析三層包的類(lèi)型后,調(diào)用對(duì)應(yīng)的三層處理去處理箱熬,三層收到包后类垦,進(jìn)行拆包,解析四層包的類(lèi)型后城须,調(diào)用對(duì)應(yīng)的四層函數(shù)去處理蚤认。每一層都有對(duì)應(yīng)的入口函數(shù),如ip_rcv是三層的入口函數(shù)糕伐,tcp_rcv是四層tcp的入口函數(shù)砰琢。

網(wǎng)絡(luò)協(xié)議棧也是可以重入的,如各種封包赤炒,已vxlan發(fā)送數(shù)據(jù)包為例氯析,當(dāng)數(shù)據(jù)包分別經(jīng)過(guò)四層、三層莺褒、二層的處理后掩缓,到達(dá)vxlan驅(qū)動(dòng),vlan驅(qū)動(dòng)處理時(shí)遵岩,又調(diào)用相應(yīng)的函數(shù)重新回到了四層處理你辣,接下來(lái)又通過(guò)三層巡通、二層的處理,最后通過(guò)物理網(wǎng)卡發(fā)送出去舍哄。

vlan子接口

vlan網(wǎng)卡是一個(gè)虛擬的網(wǎng)絡(luò)設(shè)備宴凉,下面簡(jiǎn)要介紹vlan子接口的創(chuàng)建、vlan虛擬網(wǎng)卡的收發(fā)包流程表悬、以及為什么不能創(chuàng)建相同vlanid的子接口弥锄。

創(chuàng)建vlan虛機(jī)網(wǎng)卡

ip link add link enp1 name enp1.100 type vlan id 100

上面就是創(chuàng)建vlan子接口的命令,其中 enp1 是物理網(wǎng)卡的名稱(chēng)蟆沫,enp1.100是vlan子接口的名稱(chēng)(名稱(chēng)可以隨便起籽暇,enp1.100只是可以簡(jiǎn)明的表示出來(lái)邏輯關(guān)系),id 100表示封vlan包時(shí)使用的id是100饭庞。之后當(dāng)要發(fā)送的數(shù)據(jù)包達(dá)到enp1.100時(shí)戒悠,vlan驅(qū)動(dòng)會(huì)將數(shù)據(jù)包加上vlan tag,之后轉(zhuǎn)交給主設(shè)備enp1物理網(wǎng)卡進(jìn)行發(fā)送舟山。

vlan驅(qū)動(dòng)收發(fā)包

  • vlan驅(qū)動(dòng)收包
    __netif_receive_skb_core函數(shù)是二層處理中一個(gè)很重要的函數(shù)绸狐,下面簡(jiǎn)要分析一下這個(gè)函數(shù)(代碼只展示最關(guān)鍵部分)。
static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc,
                    struct packet_type **ppt_prev)
{
    if (skb_vlan_tag_present(skb)) {
        vlan_do_receive(&skb);
    }

    rx_handler = rcu_dereference(skb->dev->rx_handler);
    rx_handler(&skb)累盗;
    deliver_skb(skb, pt_prev, orig_dev)
}

其中寒矿,skb_vlan_tag_present用于判斷數(shù)據(jù)包有沒(méi)有vlan,如果有的話(huà)幅骄,調(diào)用vlan_do_receive進(jìn)行處理劫窒,rx_handler就是判斷一個(gè)設(shè)備是否是從設(shè)備的關(guān)鍵因素,如將一個(gè)物理網(wǎng)卡加入到linux bridge中拆座,linux bridge的驅(qū)動(dòng)就會(huì)將物理網(wǎng)卡的rx_handler進(jìn)行賦值。本來(lái)這里處理完后冠息,應(yīng)該向上傳遞數(shù)據(jù)包了挪凑,但是因?yàn)?code>rx_handler不為空,所以會(huì)調(diào)用linux bridge的相關(guān)函數(shù)被處理逛艰,簡(jiǎn)單點(diǎn)說(shuō)躏碳,就是數(shù)據(jù)包被linux bridge截胡了。

  • vlan驅(qū)動(dòng)發(fā)包
    vlan驅(qū)動(dòng)的發(fā)包函數(shù)是vlan_dev_hard_start_xmit散怖,下面簡(jiǎn)要分析這個(gè)函數(shù)菇绵,代碼只展示最關(guān)鍵的流程。
static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb,
                        struct net_device *dev)
{
    struct vlan_dev_priv vlan = vlan_dev_priv(dev);

    skb->dev = vlan->real_dev;

    vlan_tci = vlan->vlan_id;
    vlan_tci |= vlan_dev_get_egress_qos_mask(dev, skb->priority);

    __vlan_hwaccel_put_tag(skb, vlan->vlan_proto, vlan_tci);

    ret = dev_queue_xmit(skb);

       return ret;

通過(guò)vlan_dev_priv獲取到vlan設(shè)備的私有數(shù)據(jù)镇眷,將skb->dev賦值為vlan子接口的主設(shè)備咬最,再通過(guò)vlan獲取到vlan id,調(diào)用__vlan_hwaccel_put_tag進(jìn)行打vlan的tag欠动,最后通過(guò)dev_queue_xmit將數(shù)據(jù)包轉(zhuǎn)給主設(shè)備進(jìn)行發(fā)送永乌。

創(chuàng)建相同的vlan id的子網(wǎng)卡

在不同的系統(tǒng)上惑申,呈現(xiàn)的錯(cuò)誤并不一樣。

  • ubuntu 22.04 上
root@VM-0-5-ubuntu:~# ip -V
ip utility, iproute2-5.15.0, libbpf 0.5.0

root@VM-0-5-ubuntu:~# ip link add link eth0 name vlan98 type vlan id 98
Error: 8021q: VLAN device already exists.
  • centos7.6
[root@10 ~]# ip -V
ip utility, iproute2-ss170501

[root@10 ~]# ip link add link bond0 name vlan98 type vlan id 98
RTNETLINK answers: File exists

ubuntu22.04 因?yàn)閕p命令的版本比較高翅雏,很好的將錯(cuò)誤的原因展示了出來(lái)圈驼,centos7.6中ip只是提示已存在。這個(gè)錯(cuò)誤來(lái)自于內(nèi)核望几,可以看這個(gè)函數(shù)vlan_check_real_dev:

int vlan_check_real_dev(struct net_device *real_dev,
            __be16 protocol, u16 vlan_id,
            struct netlink_ext_ack *extack)
{
    if (vlan_find_dev(real_dev, protocol, vlan_id) != NULL) {
        NL_SET_ERR_MSG_MOD(extack, "VLAN device already exists");
        return -EEXIST;
    }
}

從用戶(hù)的需求角度看绩脆,確實(shí)是有創(chuàng)建多個(gè)相同vlan id的vlan子接口的需求,但是內(nèi)核為什么不支持呢橄抹? 這其實(shí)跟內(nèi)核的實(shí)現(xiàn)有關(guān)衙伶,內(nèi)核完全是可以支持的,但是本著機(jī)制和策略分離的原則害碾,vlan驅(qū)動(dòng)只是做vlan隔離矢劲,用戶(hù)需要多個(gè)相同vlan id的子接口,可以通過(guò)bridge進(jìn)行將vlan子接口與用戶(hù)的虛擬網(wǎng)卡進(jìn)行橋接即可(純屬猜測(cè))慌随。

橋接原理

如上文分析芬沉,將物理網(wǎng)卡進(jìn)行橋接,相應(yīng)的橋接驅(qū)動(dòng)都會(huì)改變物理網(wǎng)卡的rx_handler函數(shù)阁猜,進(jìn)而在__netif_receive_skb_core函數(shù)處理時(shí)攔截物理網(wǎng)卡的數(shù)據(jù)包丸逸。bond、ovs剃袍、bridge都是相同的原理黄刚。

  • ovs
ovs-vsctl add-port br-int port0

這條命令是將port0網(wǎng)卡加入到br-int的ovs橋上時(shí),對(duì)應(yīng)的ovs驅(qū)動(dòng)會(huì)做處理民效,在ovs_netdev_link函數(shù)會(huì)調(diào)用netdev_rx_handler_register將物理網(wǎng)卡的rx_handler賦值為netdev_frame_hook憔维。

struct vport *ovs_netdev_link(struct vport *vport, const char *name)
{
    vport->dev = dev_get_by_name(ovs_dp_get_net(vport->dp), name);
    
    err = netdev_rx_handler_register(vport->dev, netdev_frame_hook,
                     vport);

    return vport;
  • linux bridge
brctl add-if br0 port0

這條命令是將網(wǎng)卡port0加入到linux bridge的br0上。對(duì)應(yīng)的linux-bridge驅(qū)動(dòng)會(huì)做處理畏邢。

int br_add_if(struct net_bridge *br, struct net_device *dev,
          struct netlink_ext_ack *extack)
{
    err = netdev_rx_handler_register(dev, br_handle_frame, p);
}
  • 將物理網(wǎng)卡同時(shí)接入linux bridge和ovs橋
    調(diào)用橋接時(shí)业扒,會(huì)調(diào)用netdev_is_rx_handler_busy進(jìn)行檢測(cè),這個(gè)函數(shù)的注釋也寫(xiě)的很清楚舒萎,如果網(wǎng)卡的rx_handler已經(jīng)有值了程储,這里就會(huì)返回true。從邏輯的角度也能想清楚臂寝,如果對(duì)于一個(gè)函數(shù)變量重復(fù)賦值章鲤,必然導(dǎo)致變量值被覆蓋,這顯然也是不合理的咆贬。
/**
 *  netdev_is_rx_handler_busy - check if receive handler is registered
 *  @dev: device to check
 *
 *  Check if a receive handler is already registered for a given device.
 *  Return true if there one.
 *
 *  The caller must hold the rtnl_mutex.
 */
bool netdev_is_rx_handler_busy(struct net_device *dev)
{
    ASSERT_RTNL();
    return dev && rtnl_dereference(dev->rx_handler);
}

流量走向總結(jié)

從最上面的部署關(guān)系圖看到败徊,bond0是ovs橋的從設(shè)備,vlan虛擬網(wǎng)卡的上層設(shè)備是bond0素征,如果一個(gè)數(shù)據(jù)包是帶vlan tag的集嵌,在內(nèi)核中是如何處理的呢萝挤,從__netif_receive_skb_core的處理也可以看到,是先調(diào)用vlan_do_recieve進(jìn)行處理根欧,再看網(wǎng)卡的rx_handler是否有值怜珍。

總結(jié)

本文簡(jiǎn)要的介紹了vlan虛擬網(wǎng)卡和各種橋接的原理,但是并沒(méi)有太多的去關(guān)注細(xì)節(jié)凤粗。希望本文的解讀酥泛,可以幫助各位更好的理解網(wǎng)絡(luò)的基本原理,讓心中懸而未決的疑問(wèn)更加的清晰嫌拣,最后祝各位看官看的開(kāi)心柔袁、生活愉快。創(chuàng)作不易异逐,假如文章對(duì)你有幫助捶索,記得點(diǎn)贊支持。如果有其他問(wèn)題灰瞻,可以直接評(píng)論腥例,或者加微信進(jìn)行更深入的交流。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末酝润,一起剝皮案震驚了整個(gè)濱河市燎竖,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌要销,老刑警劉巖构回,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異疏咐,居然都是意外死亡纤掸,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)凳鬓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)茁肠,“玉大人,你說(shuō)我怎么就攤上這事缩举。” “怎么了匹颤?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵仅孩,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我印蓖,道長(zhǎng)辽慕,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任赦肃,我火速辦了婚禮溅蛉,結(jié)果婚禮上公浪,老公的妹妹穿的比我還像新娘。我一直安慰自己船侧,他們只是感情好欠气,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著镜撩,像睡著了一般预柒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上袁梗,一...
    開(kāi)封第一講書(shū)人閱讀 51,365評(píng)論 1 302
  • 那天宜鸯,我揣著相機(jī)與錄音,去河邊找鬼遮怜。 笑死淋袖,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的锯梁。 我是一名探鬼主播即碗,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼涝桅!你這毒婦竟也來(lái)了拜姿?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤冯遂,失蹤者是張志新(化名)和其女友劉穎蕊肥,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體蛤肌,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡壁却,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了裸准。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片展东。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖炒俱,靈堂內(nèi)的尸體忽然破棺而出盐肃,到底是詐尸還是另有隱情,我是刑警寧澤权悟,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布砸王,位于F島的核電站,受9級(jí)特大地震影響峦阁,放射性物質(zhì)發(fā)生泄漏谦铃。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一榔昔、第九天 我趴在偏房一處隱蔽的房頂上張望驹闰。 院中可真熱鬧瘪菌,春花似錦、人聲如沸嘹朗。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)骡显。三九已至疆栏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間惫谤,已是汗流浹背壁顶。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留溜歪,地道東北人若专。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像蝴猪,于是被迫代替她去往敵國(guó)和親调衰。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容