惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
V2EX
aimingoo的专栏
aimingoo的专栏
S
SegmentFault 最新的问题
博客园_首页
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
IT之家
IT之家
博客园 - 【当耐特】
月光博客
月光博客
C
Check Point Blog
T
The Blog of Author Tim Ferriss
罗磊的独立博客
博客园 - Franky
MongoDB | Blog
MongoDB | Blog
H
Help Net Security
Microsoft Security Blog
Microsoft Security Blog
B
Blog
阮一峰的网络日志
阮一峰的网络日志
腾讯CDC
美团技术团队
N
Netflix TechBlog - Medium
Stack Overflow Blog
Stack Overflow Blog
Y
Y Combinator Blog
L
LangChain Blog
The Cloudflare Blog

hwchiu learning note Blog

Kubernetes 怎麼計算 imageFS | hwchiu learning note Nginx Proxy_Pass 不會重新查詢 DNS | hwchiu learning note Multus 下如何透過 network policy 設定 | hwchiu learning note Kubevirt 初體驗 | hwchiu learning note [MacOS ]隨手筆記 Sed 與 Rename 的使用 | hwchiu learning note Docusaurus 使用 blog mode 後連結一直反白的問題 | hwchiu learning note gcloud 切換帳號 | hwchiu learning note k8s 內安裝 redis-cluster | hwchiu learning note Helm Chart 中如何根據條件來動態安裝 Template 內的物件 | hwchiu learning note GCS 操作上注意事項 | hwchiu learning note istio 操作記錄 | hwchiu learning note terraform | hwchiu learning note Kubernetes GKE 維運上小筆記 | hwchiu learning note Git 修改 author/committer | hwchiu learning note GCP NAT 相關筆記 | hwchiu learning note gcloud ssh 到 GCP VM | hwchiu learning note CloudSQL 收費注意事項 | hwchiu learning note Loki 安裝上的參數調整以及 Ring 的問題除錯 | hwchiu learning note kustomize + helm | hwchiu learning note 觀測 K8s 內 OOM 事件 | hwchiu learning note GKE 上的 RBAC 筆記 | hwchiu learning note 本地產生 jwt token | hwchiu learning note ArgoCD 安裝筆記 | hwchiu learning note CircleCI Context 的使用 | hwchiu learning note 透過 GCP IAP Gateway 來保護 GKE 內的網站 | hwchiu learning note 閱讀筆記: 「SRE 的工作介绍」 | hwchiu learning note 閱讀筆記: 「DevOps is a failure」 | hwchiu learning note 閱讀筆記: 「面試人生 - 設計一個簡易的分散式 Job Scheduler」 | hwchiu learning note 閱讀筆記: 「Cloudflare 06/21 災後報告」 | hwchiu learning note 閱讀筆記: 「啟動 container 直接 kernel panic 的 bug」 | hwchiu learning note
Linux Bridge MTU | hwchiu learning note
HungWei ChiuBlogger · 2023-10-31 · via hwchiu learning note Blog

Linux Bridge 的 MTU 設定不如一般網卡簡單設定,其 MTU 預設情況下會自動調整,會自動使用所有 slave 網卡上最小的值來取代 以下列程式碼來看,剛有任何 slave 網卡加入到 bridge 上後

int br_add_if(struct net_bridge *br, struct net_device *dev,
struct netlink_ext_ack *extack)
{
struct net_bridge_port *p;
int err = 0;
unsigned br_hr, dev_hr;
bool changed_addr, fdb_synced = false;

/* Don't allow bridging non-ethernet like devices. */
if ((dev->flags & IFF_LOOPBACK) ||
dev->type != ARPHRD_ETHER || dev->addr_len != ETH_ALEN ||
!is_valid_ether_addr(dev->dev_addr))
return -EINVAL;

/* No bridging of bridges */
if (dev->netdev_ops->ndo_start_xmit == br_dev_xmit) {
NL_SET_ERR_MSG(extack,
"Can not enslave a bridge to a bridge");
return -ELOOP;
}

/* Device has master upper dev */
if (netdev_master_upper_dev_get(dev))
return -EBUSY;

/* No bridging devices that dislike that (e.g. wireless) */
if (dev->priv_flags & IFF_DONT_BRIDGE) {
NL_SET_ERR_MSG(extack,
"Device does not allow enslaving to a bridge");
return -EOPNOTSUPP;
}

p = new_nbp(br, dev);
if (IS_ERR(p))
return PTR_ERR(p);

call_netdevice_notifiers(NETDEV_JOIN, dev);

err = dev_set_allmulti(dev, 1);
if (err) {
br_multicast_del_port(p);
netdev_put(dev, &p->dev_tracker);
kfree(p); /* kobject not yet init'd, manually free */
goto err1;
}

err = kobject_init_and_add(&p->kobj, &brport_ktype, &(dev->dev.kobj),
SYSFS_BRIDGE_PORT_ATTR);
if (err)
goto err2;

err = br_sysfs_addif(p);
if (err)
goto err2;

err = br_netpoll_enable(p);
if (err)
goto err3;

err = netdev_rx_handler_register(dev, br_get_rx_handler(dev), p);
if (err)
goto err4;

dev->priv_flags |= IFF_BRIDGE_PORT;

err = netdev_master_upper_dev_link(dev, br->dev, NULL, NULL, extack);
if (err)
goto err5;

dev_disable_lro(dev);

list_add_rcu(&p->list, &br->port_list);

nbp_update_port_count(br);
if (!br_promisc_port(p) && (p->dev->priv_flags & IFF_UNICAST_FLT)) {
/* When updating the port count we also update all ports'
* promiscuous mode.
* A port leaving promiscuous mode normally gets the bridge's
* fdb synced to the unicast filter (if supported), however,
* `br_port_clear_promisc` does not distinguish between
* non-promiscuous ports and *new* ports, so we need to
* sync explicitly here.
*/
fdb_synced = br_fdb_sync_static(br, p) == 0;
if (!fdb_synced)
netdev_err(dev, "failed to sync bridge static fdb addresses to this port\n");
}

netdev_update_features(br->dev);

br_hr = br->dev->needed_headroom;
dev_hr = netdev_get_fwd_headroom(dev);
if (br_hr < dev_hr)
update_headroom(br, dev_hr);
else
netdev_set_rx_headroom(dev, br_hr);

if (br_fdb_add_local(br, p, dev->dev_addr, 0))
netdev_err(dev, "failed insert local address bridge forwarding table\n");

if (br->dev->addr_assign_type != NET_ADDR_SET) {
/* Ask for permission to use this MAC address now, even if we
* don't end up choosing it below.
*/
err = dev_pre_changeaddr_notify(br->dev, dev->dev_addr, extack);
if (err)
goto err6;
}

err = nbp_vlan_init(p, extack);
if (err) {
netdev_err(dev, "failed to initialize vlan filtering on this port\n");
goto err6;
}

spin_lock_bh(&br->lock);
changed_addr = br_stp_recalculate_bridge_id(br);

if (netif_running(dev) && netif_oper_up(dev) &&
(br->dev->flags & IFF_UP))
br_stp_enable_port(p);
spin_unlock_bh(&br->lock);

br_ifinfo_notify(RTM_NEWLINK, NULL, p);

if (changed_addr)
call_netdevice_notifiers(NETDEV_CHANGEADDR, br->dev);

br_mtu_auto_adjust(br);
br_set_gso_limits(br);

kobject_uevent(&p->kobj, KOBJ_ADD);

return 0;

err6:
if (fdb_synced)
br_fdb_unsync_static(br, p);
list_del_rcu(&p->list);
br_fdb_delete_by_port(br, p, 0, 1);
nbp_update_port_count(br);
netdev_upper_dev_unlink(dev, br->dev);
err5:
dev->priv_flags &= ~IFF_BRIDGE_PORT;
netdev_rx_handler_unregister(dev);
err4:
br_netpoll_disable(p);
err3:
sysfs_remove_link(br->ifobj, p->dev->name);
err2:
br_multicast_del_port(p);
netdev_put(dev, &p->dev_tracker);
kobject_put(&p->kobj);
dev_set_allmulti(dev, -1);
err1:
return err;
}

其中上述的重點是 br_mtu_auto_adjust,該 function 的內容如下,基本上就去找出最小MTU並且設定

void br_mtu_auto_adjust(struct net_bridge *br)
{
ASSERT_RTNL();

/* if the bridge MTU was manually configured don't mess with it */
if (br_opt_get(br, BROPT_MTU_SET_BY_USER))
return;

/* change to the minimum MTU and clear the flag which was set by
* the bridge ndo_change_mtu callback
*/
dev_set_mtu(br->dev, br_mtu_min(br));
br_opt_toggle(br, BROPT_MTU_SET_BY_USER, false);
}