Linux网络协议栈4--bridge收发包

bridge 是linux上的虚拟交换机,具有交换机的功能。

网卡收到包后,走到__netif_receive_skb_core后,剥完vlan找到vlan子接口(如果有的话),如果skb->dev是bridge成员口,就会走到bridge成员口的接收处理函数。

static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc)
{
......
	/*
	bridge、ovs的接口,都会走到。
	如果一个dev被添加到一个bridge(做为bridge的一个接口),这个接口设备的rx_handler将被设置为,
	br_handle_frame函数这是在br_add_if函数中设置的,而br_add_if (net/bridge/br_if.c)是在向
	网桥设备上添加接口时设置的。进入br_handle_frame也就进入了bridge的逻辑代码。*/
	rx_handler = rcu_dereference(skb->dev->rx_handler);
	if (rx_handler) {
		if (pt_prev) {
			ret = deliver_skb(skb, pt_prev, orig_dev);
			pt_prev = NULL;
		}
		switch (rx_handler(&skb)) {
		case RX_HANDLER_CONSUMED:  // 报文已经被消费,结束处理
			ret = NET_RX_SUCCESS;
			goto out;
		case RX_HANDLER_ANOTHER:  // skb->dev 被修改,重新走一次
			goto another_round;
		case RX_HANDLER_EXACT: /* 精确传递到ptype->dev == skb->dev */
			deliver_exact = true;
		case RX_HANDLER_PASS:
			break;
		default:
			BUG();
		}
	}

	......
}

bridge 的接收处理函数为br_handler_frame,在为bridge添加接口操作时,如brctl addif命令行将一个接口加入到bridge中,就会为接口的 net_device挂载此处理函数。

int br_add_if(struct net_bridge *br, struct net_device *dev)
{
	......
	err = netdev_rx_handler_register(dev, br_handle_frame, p);
	if (err)
		goto err4;

	......
}

int netdev_rx_handler_register(struct net_device *dev,
			       rx_handler_func_t *rx_handler,
			       void *rx_handler_data)
{
	ASSERT_RTNL();

	if (dev->rx_handler)
		return -EBUSY;

	/* Note: rx_handler_data must be set before rx_handler */
	rcu_assign_pointer(dev->rx_handler_data, rx_handler_data);
	rcu_assign_pointer(dev->rx_handler, rx_handler);

	return 0;
}

bridge接收处理函数br_handle_frame,非linklocal地址的情况下,主要做:
1、ebtables 的BROUTING 表处理,这是在bridge协议栈中将二层转发切换到主机协议栈的三层转发的hook点;
2、bridge NF_BR_PRE_ROUTING hook点处理,配置net.bridge.bridge-nf-call-iptables 系统配置的情况下还会 调用iptables规则处理;
3、进br_handle_frame_finish函数,根据src mac学习fdb表项,继续做转发处理或本机报文上送三层协议栈。

rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
{
	struct net_bridge_port *p;
	struct sk_buff *skb = *pskb;
	const unsigned char *dest = eth_hdr(skb)->h_dest;
	br_should_route_hook_t *rhook;

	if (unlikely(skb->pkt_type == PACKET_LOOPBACK))
		return RX_HANDLER_PASS;

	if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
		goto drop;
	// 如果skb被其它流程共享,clone一份
	skb = skb_share_check(skb, GFP_ATOMIC);
	if (!skb)
		return RX_HANDLER_CONSUMED;

	p = br_port_get_rcu(skb->dev);

	if (unlikely(is_link_local_ether_addr(dest))) {
		u16 fwd_mask = p->br->group_fwd_mask_required;

		/*
		 * See IEEE 802.1D Table 7-10 Reserved addresses
		 *
		 * Assignment		 		Value
		 * Bridge Group Address		01-80-C
  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您好!对于华为交换机的动态链路聚合配置,您可以按照以下步骤进行操作: 1. 创建一个聚合组:在交换机上执行以下命令创建一个聚合组: ``` <交换机> system-view [交换机] interface bridge-aggregation group-number [交换机-Bridge-Aggregation1] quit ``` 2. 配置聚合组的成员接口:将需要聚合的接口添加到聚合组中。假设您有两个需要聚合的接口(如GE0/0/1和GE0/0/2),可以执行以下命令: ``` <交换机> system-view [交换机] interface gigabitethernet 0/0/1 [交换机-GigabitEthernet0/0/1] port link-aggregation group group-number [交换机-GigabitEthernet0/0/1] quit [交换机] interface gigabitethernet 0/0/2 [交换机-GigabitEthernet0/0/2] port link-aggregation group group-number [交换机-GigabitEthernet0/0/2] quit [交换机] quit ``` 3. 配置聚合组的链路聚合控制协议(LACP):您可以选择启用链路聚合控制协议以实现动态链路聚合。执行以下命令来启用LACP: ``` <交换机> system-view [交换机] interface bridge-aggregation group-number [交换机-Bridge-Aggregation1] lacp enable [交换机-Bridge-Aggregation1] quit ``` 4. 配置聚合组的链路聚合模式:您可以选择链路聚合模式,如静态、动态或主动。执行以下命令配置链路聚合模式为动态: ``` <交换机> system-view [交换机] interface bridge-aggregation group-number [交换机-Bridge-Aggregation1] mode lacp-dynamic [交换机-Bridge-Aggregation1] quit ``` 5. 验证配置:您可以使用以下命令验证动态链路聚合的配置情况: ``` <交换机> display interface bridge-aggregation group-number ``` 请注意,上述命令中的 "group-number" 是您为聚合组选择的组号。根据您的实际需求,可以选择不同的组号和接口。另外,请根据您的设备型号和软件版本进行适当的调整。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值