Linux内核bridge浅析

Linux 内核下Bridge配置以及报文处理流程实现 作为网络工程师,对于报文二三层转发过程应该比较熟悉,那么对于常见的bridge接口转发、vlan报文转发在Linux内核中是如何实现的,却不是很清楚,希望就此问题能和大家一起了解学习,这里从概念、配置、报文处理几个方面先对Bridge进行了解学习。 阅读详情

原文地址:http://blog.chinaunix.net/uid-20662820-id-3413865.html

Linux网桥模型:

       Linux内核通过一个虚拟的网桥设备来实现桥接的,这个设备可以绑定若干个以太网接口设备,从而将它们桥接起来。如下图所示:

 

网桥设备br0绑定了eth0和eth1。对于网络协议栈的上层来说,只看得到br0,因为桥接是在数据链路层实现的,上层不需要关心桥接的细节。于是协议栈上层需要发送的报文被送到br0,网桥设备的处理代码再来判断报文该被转发到eth0或是eth1,或者两者皆是;反过来,从eth0或从eth1接收到的报文被提交给网桥的处理代码,在这里会判断报文该转发、丢弃、或提交到协议栈上层。
    而有时候eth0、eth1也可能会作为报文的源地址或目的地址,直接参与报文的发送与接收(从而绕过网桥)。

 

相关数据结构:

 

   其中最左边的net_device是一个代表网桥的虚拟设备结构,它关联了一个net_bridge结构,这是网桥设备所特有的数据结构。
   在net_bridge结构中,port_list成员下挂一个链表,链表中的每一个节点(net_bridge_port结构)关联到一个真实的网口设备的net_device。网口设备也通过其br_port指针做反向的关联(那么显然,一个网口最多只能同时被绑定到一个网桥)。
net_bridge结构中还维护了一个hash表,是用来处理地址学习的。当网桥准备转发一个报文时,以报文的目的Mac地址为key,如果可以在hash表中索引到一个net_bridge_fdb_entry结构,通过这个结构能找到一个网口设备的net_device,于是报文就应该从这个网口转发出去;否则,报文将从所有网口转发。

 

网桥数据包的处理流程:

  

   接收过程:

   对于数据包的处理流程并没有明显的主线,主要就是根据内核代码中网桥部分的源码进行分析。

   网口设备接收到的报文最终通过net_receive_skb函数被网络协议栈所接收。这个函数主要做三件事情:1、如果有抓包程序需要skb,将skb复制给它们;2、处理桥接;3、将skb提交给网络层。


点击(此处)折叠或打开

  1. int netif_receive_skb(struct sk_buff *skb)
  2. {
  3. ......
  4.  if (handle_bridge(&skb, &pt_prev, &ret, orig_dev))
  5.   goto out;
  6. ......
  7. }
  8. static inline struct sk_buff *handle_bridge(struct sk_buff *skb,
  9.                                        struct packet_type **pt_prev, int *ret,
  10.                                        struct net_device *orig_dev)
  11. {
  12.        struct net_bridge_port *port;
  13.        //对于回环设备以及skb->dev->br_port为空(即不被任何网桥所包含)的数据包直接返回
  14.        if (skb->pkt_type == PACKET_LOOPBACK ||
  15.            (port = rcu_dereference(skb->dev->br_port)) == NULL)
  16.               return skb;
  17.  
  18.        if (*pt_prev) {
  19.               *ret = deliver_skb(skb, *pt_prev, orig_dev);
  20.               *pt_prev = NULL;
  21.        }
  22.        //网桥的基本挂接点处理函数
  23.        return br_handle_frame_hook(port, skb);
  24. }
  25. br_handle_frame_hook在网桥初始化模块br_init(void)函数中被赋值.
  26. br_handle_frame_hook = br_handle_frame;
  27. 所以网桥对于数据包的处理过程是从br_handle_frame开始的。
  28. struct sk_buff *br_handle_frame(struct net_bridge_port *p, struct sk_buff *skb)
  29. {
  30.        const unsigned char *dest = eth_hdr(skb)->h_dest;
  31.        int (*rhook)(struct sk_buff *skb);
  32.  
  33.     //判断是否为有效的物理地址,非全0地址以及非广播地址
  34.        if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
  35.               goto drop;
  36.  
  37.        //判断skb包是否被共享skb->users != 1,若是,则复制一份,否则直接返回
  38.        skb = skb_share_check(skb, GFP_ATOMIC);
  39.        if (!skb)
  40.               return NULL;
  41.  
  42.        //这个函数并非像想象的那样,判断是否为本地地址
  43.        //而是在判断是否为链路本地多播地址,01:80:c2:00:00:0x
  44.        if (unlikely(is_link_local(dest))) {
  45.               /* Pause frames shouldn't be passed up by driver anyway */
  46.               if (skb->protocol == htons(ETH_P_PAUSE))
  47.                      goto drop;
  48.               /* If STP is turned off, then forward */
  49.               if (p->br->stp_enabled == BR_NO_STP && dest[5] == 0)
  50.                      goto forward;
  51.  
  52.               if (NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev,
  53.                          NULL, br_handle_local_finish))
  54.                      return NULL; /* frame consumed by filter */
  55.               else
  56.                      return skb; /* continue processing */
  57.        }
  58.  
  59. forward:
  60.        switch (p->state) {
  61.        case BR_STATE_FORWARDING:
  62.        //如果网桥处于forwarding状态,并且该报文必须要走L3层进行转发,则直接返回
  63.        //br_should_route_hook钩子函数在ebtable里面设置为ebt_broute函数,它根据用户的规
  64.     //决定该报文是否要通过L3层来转发;一般rhook为空
  65.        rhook = rcu_dereference(br_should_route_hook);
  66.               if (rhook != NULL) {
  67.                      if (rhook(skb))
  68.                             return skb;
  69.                      dest = eth_hdr(skb)->h_dest;
  70.               }
  71.               /* fall through */
  72.        case BR_STATE_LEARNING:
  73.               //如果数据包的目的mac地址为虚拟网桥设备的mac地址,则标记为host
  74.               if (!compare_ether_addr(p->br->dev->dev_addr, dest))
  75.                      skb->pkt_type = PACKET_HOST;
  76. //调用网桥在NF_BR_PREROUTING处挂载的钩子函数,因为网桥在其钩子函数过//程中嵌套调用了INET层BR_PREROUTING的钩子函数,过程有些曲折,故最后//再分析
  77.               NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
  78.                      br_handle_frame_finish);
  79.               break;
  80.        default:
  81. drop:
  82.               kfree_skb(skb);
  83.        }
  84.        return NULL;
  85. }
  86. FORWARDING以及LEARNING为网桥的状态,网桥端口一般有5种状态:
  87. 1) disable 被管理员禁用
  88. 2) blcok 休息,不参与数据包转发
  89. 3) listening 监听
  90. 4) learning 学习ARP信息,准备向工作状态改变
  91. 5) forwarding 正常工作,转发数据包
  92. /* note: already called with rcu_read_lock (preempt_disabled) */
  93. int br_handle_frame_finish(struct sk_buff *skb)
  94. {
  95.        const unsigned char *dest = eth_hdr(skb)->h_dest;
  96.        struct net_bridge_port *p = rcu_dereference(skb->dev->br_port);
  97.        struct net_bridge *br;
  98.        struct net_bridge_fdb_entry *dst;
  99.        struct sk_buff *skb2;
  100.  
  101.        //判断网桥状态
  102.        if (!p || p->state == BR_STATE_DISABLED)
  103.               goto drop;
  104.  
  105.        /* insert into forwarding database after filtering to avoid spoofing */
  106.        //br为虚拟网桥结构
  107.        br = p->br;
  108.        //根据数据包的源物理地址,更新网桥的转发表
  109.        br_fdb_update(br, p, eth_hdr(skb)->h_source);
  110.  
  111.        if (p->state == BR_STATE_LEARNING)
  112.               goto drop;
  113.  
  114.        /* The packet skb2 goes to the local host (NULL to skip). */
  115.        //skb2数据包用于交付本机,skb数据包则用于forward
  116.        skb2 = NULL;
  117.        //如果网口处于混杂模式,复制一份交付主机
  118.        if (br->dev->flags & IFF_PROMISC)
  119.               skb2 = skb;
  120.  
  121.        dst = NULL;
  122.  
  123.        //如果为广播数据包,增加计数,同样需要发一份给主机
  124.        if (is_multicast_ether_addr(dest)) {
  125.               br->dev->stats.multicast++;
  126.               skb2 = skb;
  127.        }
  128.        /*根据网桥口以及目标地址判断是否为本机数据包*/
  129.        else if ((dst = __br_fdb_get(br, dest)) && dst->is_local) {
  130.               skb2 = skb;
  131.               /* Do not forward the packet since it's local. */
  132.               skb = NULL;
  133.        }
  134.  
  135.        if (skb2 == skb)
  136.               skb2 = skb_clone(skb, GFP_ATOMIC);
  137.  
  138.        if (skb2)
  139.               /*完成将数据包交付给本机的工作*/
  140.               br_pass_frame_up(br, skb2);
  141.  
  142.        if (skb) {
  143.               if (dst)
  144.                      //如果存在目的地址则将其转发
  145.                      br_forward(dst->dst, skb);
  146.               else
  147.                      //否则,flood数据包,向除接收网口外的其余网口发送该数据包
  148.                      br_flood_forward(br, skb);
  149.        }
  150.  
  151. out:
  152.        return 0;
  153. drop:
  154.        kfree_skb(skb);
  155.        goto out;
  156. }
  157.  
  158. //此函数主要实现通过网桥接收发往本机的数据包
  159. static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb)
  160. {
  161.        struct net_device *indev, *brdev = br->dev;
  162.  
  163.        //完成数据包的统计计数
  164.        brdev->stats.rx_packets++;
  165.        brdev->stats.rx_bytes += skb->len;
  166.  
  167.        //将skb的dev改变为网桥结构的brdev
  168.        //此时skb的dev选项由实际网络设备eth0等改变为虚拟网桥设备br0
  169.        indev = skb->dev;
  170.        skb->dev = brdev;
  171.  
  172.        //重新走数据包接收流程,netif_receive_skb
  173.        //但因为dev的改变,dev的br_port字段不再为空,不会重走网桥流程,直接交付
  174.        NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL,
  175.               netif_receive_skb);
  176. }
  177.  
  178. 下面看一下转发数据包的流程,对于flood_forward的流程,同样通过br_forward来实现,只不过改为循环遍历hash表中的设备,对于每一个设备都调用一次br_forward流程。
  179. /* called with rcu_read_lock */
  180. void br_forward(const struct net_bridge_port *to, struct sk_buff *skb)
  181. {
  182.        /*如果skb->dev 不等于网桥的dev,同时网桥状态为forwarding,则进行转发*/
  183.        if (should_deliver(to, skb)) {
  184.               __br_forward(to, skb);
  185.               return;
  186.        }
  187.  
  188.        kfree_skb(skb);
  189. }
  190. static void __br_forward(const struct net_bridge_port *to, struct sk_buff *skb)
  191. {
  192.        struct net_device *indev;
  193.  
  194.        if (skb_warn_if_lro(skb)) {
  195.               kfree_skb(skb);
  196.               return;
  197.        }
  198.        //将skb的dev字段改为查找到的出口dev字段
  199.        indev = skb->dev;
  200.        skb->dev = to->dev;
  201.        skb_forward_csum(skb);
  202.        //遍历执行NF_BR_FORWARD钩子函数
  203.        NF_HOOK(PF_BRIDGE, NF_BR_FORWARD, skb, indev, skb->dev,
  204.                      br_forward_finish);
  205. }
  206. int br_forward_finish(struct sk_buff *skb)
  207. {
  208.        //继续跑NF_BR_POST_ROUTING处的钩子函数
  209.        return NF_HOOK(PF_BRIDGE, NF_BR_POST_ROUTING, skb, NULL, skb->dev,
  210.                      br_dev_queue_push_xmit);
  211. }
  212. int br_dev_queue_push_xmit(struct sk_buff *skb)
  213. {
  214.        /* drop mtu oversized packets except gso */
  215.        /*如果skb数据包的长度大于MTU值,则丢弃*/
  216.        if (packet_length(skb) > skb->dev->mtu && !skb_is_gso(skb))
  217.               kfree_skb(skb);
  218.        else {
  219.               /* ip_refrag calls ip_fragment, doesn't copy the MAC header. */
  220.               if (nf_bridge_maybe_copy_header(skb))
  221.                      kfree_skb(skb);
  222.               else {
  223.                      skb_push(skb, ETH_HLEN);
  224.          // 此时skb的dev已经替换成进行转发的dev了,dev_queue_xmit将使
  225. //用该网口设备的发送函数完成数据包的发送
  226.                      dev_queue_xmit(skb);
  227.               }
  228.        }
  229.  
  230.        return 0;
  231. }
  232.  
  233. 发送过程:
  234.        协议栈上层需要发送报文时,调用dev_queue_xmit(skb)函数。如果这个报文需要通过网桥设备来发送,则skb->dev指向一个网桥设备。网桥设备没有使用发送队列(dev->qdisc为空),所以dev_queue_xmit将直接调用dev->hard_start_xmit函数,而网桥设备的hard_start_xmit等于函数br_dev_xmit;
  235. /* net device transmit always called with no BH (preempt_disabled) */
  236. /*br_dev_xmit为网桥设备的数据包发送函数*/
  237. int br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
  238. {
  239.        struct net_bridge *br = netdev_priv(dev);
  240.        const unsigned char *dest = skb->data;
  241.        struct net_bridge_fdb_entry *dst;
  242.  
  243.        dev->stats.tx_packets++;
  244.        dev->stats.tx_bytes += skb->len;
  245.  
  246.        skb_reset_mac_header(skb);
  247.        skb_pull(skb, ETH_HLEN);
  248.  
  249.        /*如果为广播地址,则flood该数据包
  250.        * 如果能够根据skb中的目的mac地址查找到对应的网口,则通过br_deliver发送该数据包
  251.        * 如果查找不到,同样flood该数据包
  252.        */
  253.        if (dest[0] & 1)
  254.               br_flood_deliver(br, skb);
  255.        else if ((dst = __br_fdb_get(br, dest)) != NULL)
  256.               br_deliver(dst->dst, skb);
  257.        else
  258.               br_flood_deliver(br, skb);
  259.  
  260.        return 0;
  261. }
  262. br_flood_deliver函数的实现过程,同样是遍历hash表,对于每一个网口设备都调用一次__br_deliver,所以下面就主要看一下br_deliver函数的流程
  263. void br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)
  264. {
  265.        if (should_deliver(to, skb)) {
  266.               __br_deliver(to, skb);
  267.               return;
  268.        }
  269.  
  270.        kfree_skb(skb);
  271. }
  272. static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)
  273. {
  274.        /*将skb中的dev改成出口设备所对应的dev*/
  275.        skb->dev = to->dev;
  276.        NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
  277.                      br_forward_finish);
  278. }
  279. /*最终仍然通过br_dev_queue_push_xmit完成数据包的发送过程*/
  280. int br_forward_finish(struct sk_buff *skb)
  281. {
  282.        return NF_HOOK(PF_BRIDGE, NF_BR_POST_ROUTING, skb, NULL, skb->dev,
  283.                      br_dev_queue_push_xmit);
  284.  
  285. }
  286. 至此,整个网桥中数据的处理流程已经完全结束了。
  287.  
  288.  
  289. Netfilter:
  290.  
  291. 对于网桥中的netfilter的钩子函数的调度过程有些曲折,对于INET层的钩子函数全部被嵌套进BRIDGE层钩子函数的运行流程中。
  292. 下面首先来看一下网桥一共挂载了哪些钩子函数
  293. static struct nf_hook_ops br_nf_ops[] __read_mostly = {
  294.        { .hook = br_nf_pre_routing,
  295.          .owner = THIS_MODULE,
  296.          .pf = PF_BRIDGE,
  297.          .hooknum = NF_BR_PRE_ROUTING,
  298.          .priority = NF_BR_PRI_BRNF, },
  299.        { .hook = br_nf_local_in,
  300.          .owner = THIS_MODULE,
  301.          .pf = PF_BRIDGE,
  302.          .hooknum = NF_BR_LOCAL_IN,
  303.          .priority = NF_BR_PRI_BRNF, },
  304.        { .hook = br_nf_forward_ip,
  305.          .owner = THIS_MODULE,
  306.          .pf = PF_BRIDGE,
  307.          .hooknum = NF_BR_FORWARD,
  308.          .priority = NF_BR_PRI_BRNF - 1, },
  309.        { .hook = br_nf_forward_arp,
  310.          .owner = THIS_MODULE,
  311.          .pf = PF_BRIDGE,
  312.          .hooknum = NF_BR_FORWARD,
  313.          .priority = NF_BR_PRI_BRNF, },
  314.        { .hook = br_nf_local_out,
  315.          .owner = THIS_MODULE,
  316.          .pf = PF_BRIDGE,
  317.          .hooknum = NF_BR_LOCAL_OUT,
  318.          .priority = NF_BR_PRI_FIRST, },
  319.        { .hook = br_nf_post_routing,
  320.          .owner = THIS_MODULE,
  321.          .pf = PF_BRIDGE,
  322.          .hooknum = NF_BR_POST_ROUTING,
  323.          .priority = NF_BR_PRI_LAST, },
  324. //以上为BRIDGE层挂载的钩子函数,一下为INET层挂载的钩子函数
  325.        { .hook = ip_sabotage_in,
  326.          .owner = THIS_MODULE,
  327.          .pf = PF_INET,
  328.          .hooknum = NF_INET_PRE_ROUTING,
  329.          .priority = NF_IP_PRI_FIRST, },
  330.        { .hook = ip_sabotage_in,
  331.          .owner = THIS_MODULE,
  332.          .pf = PF_INET6,
  333.          .hooknum = NF_INET_PRE_ROUTING,
  334.          .priority = NF_IP6_PRI_FIRST, },
  335. };
  336. 其实在这些钩子函数内部并没有涉及数据包操作的具体流程,大多是一些条件判断和验证的工作,现在就拿发往本机的数据包在作为一个例子,看一下这个数据包在netfilter中的流经过程(自认为还算有代表意义)。
  337. 对于发往本机网桥口的skb包,其skb->dev->br_port不为空,因此会进入网桥的处理流程,br_handler_frame,在此函数的退出处会首先运行NF_BR_PRE_ROUTING的钩子函数
  338. NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
  339.                      br_handle_frame_finish);
  340. 网桥挂载在BR_PRE_ROUTING的函数为br_nf_pre_routing
  341. 在此函数内部首先完成ipv4及ipv6数据的分流,这里只考虑ipv4数据,接着进行ipv4数据正确性的验证,以及网桥标记nf_bridge->mask |= BRNF_NF_BRIDGE_PREROUTING;(下面还要用到此标记)在函数的最后通过NF_HOOK(PF_INET, NF_INET_PRE_ROUTING, skb, skb->dev, NULL,br_nf_pre_routing_finish)完成对于INET层PRE_ROUTING钩子函数的遍历。
  342. 遍历结束后进入br_nf_pre_routing_finish函数,这个函数首先对数据包打标记,nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING;(跟上一个标记对应)主要处理skb包需要进行dnat的情形(貌似,没有细看),在函数的最后
  343.        NF_HOOK_THRESH(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
  344.                      br_handle_frame_finish, 1);
  345. 在这里通过NF_HOOK_THRESH而非NF_HOOK的意思是因为,NF_HOOK_THRESH是从当前优先级的下一个函数开始遍历所有的钩子函数,在这里也就是说从br_nf_pre_routing函数的下一个优先级函数开始遍历BR_PRE_ROUTING的后续函数,虽然目前网桥只挂载了这一个函数,但是这属于Netfilter的机制问题。
  346. 接着,在跑完BR_PRE_ROUTING的剩余函数后就进入br_handle_frame_finish函数,对于本机数据包则继续调用br_pass_frame_up函数,在br_pass_frame_up函数中将skb的dev字段修改为虚拟网桥的dev,最后NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL, netif_receive_skb);将数据包重新跑skb的接收流程,由于网桥设备的dev->br_port不为空,因此不会再进入网桥处理流程了。
  347. 那网桥是怎样防止同一个skb包跑两次INET_PRE_ROUTING的流程呢,主要就是通过挂在在INET_PRE_ROUTING出优先级最高的NF_IP_PRI_FIRST处的函数ip_sabotage_in以及上文特殊提到的两个打标记的代码来完成的。
  348. static unsigned int ip_sabotage_in(unsigned int hook, struct sk_buff *skb,
  349.                                const struct net_device *in,
  350.                                const struct net_device *out,
  351.                                int (*okfn)(struct sk_buff *))
  352. {
  353.        /*此钩子函数用于确保发往本机的skb包只跑一次INET_PRE_ROUTING的钩子函数
  354.        * 在第一次进入BR_PRE_ROUTING时打上标记mask,在BR_PRE_ROUTING的钩子函数中遍历INET_PRE_ROUTING的钩子函数
  355.        * 在br_pre_routing结束的时候,异或该mask值,这样就使得发往本机的skb包在第二次交付的时候可以不再跑钩子
  356.        */
  357.        if (skb->nf_bridge &&
  358.            !(skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)) {
  359.               return NF_STOP;
  360.        }
  361.  
  362.        return NF_ACCEPT;
  363. }
  364. NF_STOP的意思就是说该skb包就立即结束检查而接受,不再进入链表中后续的hook节点。
  365.  
  366. 整个网桥模块大体就是这个样子,剩下的还有网桥的生成树协议,这周打算把这个搞懂。。。
  367. 第一次写分析,自己给自己加油,继续努力~
浅析linux内核网络协议栈--linux bridge 本文是参考附录上的资料整理而成,以帮助读者更好的理解kernel中brdige 模块代码。 阅读详情

相关推荐

浅析linux内核网络协议栈--linux bridge(二)

br_handle_local_finish的处理实际上不如说是“不处理”,它只是在端口处于Learning的情况下学习个skb的源MAC,并且总是返回0指示包 RX_HANDLER_PASS,由netif_receive_skb继续根据ptype_base处理(STP报文)。如果将这个概念扩展,其实对于转发(forward)的数据帧也是两次经过net_device,两次都是网桥端口的net_device{},函数的话,一次是netif_receive_skb,一次是dev_queue_xmit)。

m0_74282605的博客 1172

ALinux网桥的实现分析与使用

一、Linux内核网桥的实现分析 Linux 内核分别在2.2 和 2.4内核中实现了网桥。但是2.2 内核和 2.4内核的实现有很大的区别,2.4中的实现几乎是全部重写了所有的实现代码。本文以2.4.0内核版本为例进行分析。 在分析具体的实现之前,先描述几个概念,有助于对网桥的功能及实现有更深的理解。 冲突域 一个冲突域由所有能够看到同一个冲突或者被该冲突涉及到的设备组成。以...

编程资料大全 471

台达PLC DIAdesigner-AX 编程实战:从安装到通信配置

本文详细介绍了台达PLC DIAdesigner-AX编程的实战操作,从软件安装、项目创建到通信配置的全流程。重点讲解了TCP/IP通信设置、库文件管理及常见错误处理,帮助工程师快速掌握台达PLC编程技巧,提升工业自动化项目的开发效率。

weixin_29215391的博客 530

Linux下的虚拟Bridge实现

2013-04-21 23:28 by zmkeil, 290 阅读, 0 评论, 收藏, 编辑     Linux下的Bridge也是一种虚拟设备,这多少和vlan有点相似,它依赖于一个或多个从设备。与VLAN不同的是,它不是虚拟出和从设备同一层次的镜像设备,而是虚拟出一个高一层次的设备,并把从设备虚拟化为端口port,且同时处理各个从设备的数据收发及转发,再加上netfilter框架

火星上的乡巴佬的专栏 2310

游戏封包抓取实战:雷电模拟器+ProxyDroid+查尔斯3.93+WPE全流程解析

本文详细解析了使用雷电模拟器、ProxyDroid、查尔斯3.93和WPE进行游戏封包抓取的全流程实战。通过环境搭建、代理配置与工具协同,手把手教你抓取HTTP/HTTPS及原始Socket数据,涵盖从流量转向、证书安装到数据分析和常见问题排查,是学习游戏网络协议分析与安全测试的实用指南。

u8v9w0x1y的博客 443

告别实车测试:手把手教你用Vector VT平台搭建OBC/DCDC的HIL测试台架

本文详细介绍了如何利用Vector VT平台搭建新能源汽车OBC/DCDC的HIL测试台架,涵盖硬件选型、模型部署到自动化测试的全流程。通过HIL仿真测试技术,工程师可以高效验证动力域关键部件,大幅缩短开发周期并降低成本,特别适合新能源汽车三电系统的开发验证。

weixin_42659194的博客 338

linux bridge 数据 流程,Linux内核bridge中的数据包处理流程

Linux内核bridge中的数据包处理流程本文档的Copyleft归yfydz所有,使用GPL发布,可以自由拷贝,转载,转载时请保持文档的完整性,严禁用于任何商业用途。msn: yfydz_no1@hotmail.com来源:http://yfydz.cublog.cn1. 前言本文简要介绍数据包在进入桥网卡后在Linux网络协议栈的处理流程,并描述netfilter的hook点的挂接处理情况,...

weixin_31876475的博客 650

【一文读懂】NTN(非地面网络)技术介绍

NTN,即非地面网络,是指利用卫星、高空平台(如无人机、平流层气球等)等非地面通信基础设施来实现全球通信覆盖的网络。在5G时代,NTN主要基于5G标准,特别是5G NR(New Radio)技术,通过卫星通信扩展地面网络的覆盖范围和服务能力。NTN技术的出现和发展,为全球通信带来了新的可能性和挑战。通过不断的技术创新和标准化推进,NTN有望在未来发挥更加重要的作用,为全球用户提供无处不在的通信服务。随着6G时代的到来,我们有理由相信NTN技术将迎来更加广阔的发展前景。

u011376987的博客 1万+

linux内核bridge浅析,Linux内核bridge浅析.doc

Linux内核bridge浅析Linux内核bridge浅析Linux网桥模型:  Linux内核通过一个虚拟的网桥设备来实现桥接的,这个设备可以绑定若干个以太网接口设备,从而将它们桥接起来。如下图所示:网桥设备br0绑定了eth0和eth1。对于网络 HYPERLINK "/List_11.html" \t "_blank" 协议栈的上层来说,只看得到br0,因为桥接是在数据链路层实现的,上层不...

weixin_34768019的博客 237

39、低功耗处理器性能评估与Cortex - M23/M33低功耗特性解析

本文深入解析了Cortex-M23和Cortex-M33处理器的低功耗特性及其性能评估方法。介绍了ULPMark、CoreMark、IoTMark-BLE和SecureMark-TLS等基准测试在能效评估中的应用,并详细阐述了处理器的睡眠模式、系统控制寄存器(SCR)配置、WFI/WFE指令、退出时睡眠、挂起时发送事件(SEVONPEND)以及唤醒中断控制器(WIC)等关键低功耗机制。结合状态保留技术,展示了如何通过芯片级设计大幅降低泄漏电流,实现高效能低功耗的物联网与嵌入式系统设计。

Pepper的专栏 129

前沿探索:基于强化学习的目标检测与跟踪技术及论文解析

前沿探索:基于强化学习的目标检测与跟踪技术及论文解析 ,人工智能,计算机视觉,大模型,AI,本文聚焦基于强化学习的目标检测与跟踪技术,先介绍相关技术基础,包括目标检测、跟踪及强化学习的算法等。接着阐述强化学习在目标检测与跟踪中的应用思路、框架及典型算法,解析三篇相关论文的背景、方法、实验结果。还探讨了该技术面临的样本效率、奖励函数设计等挑战,以及结合迁移学习等的未来发展方向,为该领域研究提供参考。

不踩坑,不知道坑有多深;不总结,踩过的坑白踩。 11万+

linux内核seng_sig_info,Linux内核bridge浅析

int netif_receive_skb(struct sk_buff *skb){......if (handle_bridge(&skb, &pt_prev, &ret, orig_dev))goto out;......}static inline struct sk_buff *handle_bridge(struct sk_buff *skb,struct pa...

weixin_39641231的博客 225

全志V3S嵌入式驱动开发(驱动开发准备)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 之前的文章都是教大家怎么搭建环境、看原理图、编译内核和根文件系统、做镜像,直到现在才进入驱动开发的主题。毕竟整个专栏的目的,还是希望大家能够学会驱动外部硬件。驱动好硬件,分成硬件和软件两个部分,硬件的部分比较好理解,就是看相关的信号有没有对接上即可,但是软件对接、甚至于怎么写软件,大家好像接触的比较少,所以这个时候,就可以简单讨论一下,怎么样才能写驱动代码。 1、了解外部驱动芯

嵌入式-老费,一个分享专业嵌入式知识的blog 2024

Linux Bridge

Linux网桥实现分析 linux网桥浅析 Linux上桥的实现 Linux从用户层到内核层系列 - TCP/IP协议栈部分系列3: bridge(网桥)FDB表中MAC地址的更新 linux内核中VLAN收发处理 Linux 内核网桥源码分析 ...

u014044624的博客 270

OBC_开环扫频波特图拟合操作流程(结合 Simulink)

摘要: 本文详细介绍了基于Simulink的开环扫频波特图测试与拟合流程,适用于电源/控制系统(如LLC/PFC)的小信号分析。主要内容包括:1)前期准备(测试点选择、信号范围设定);2)Simulink建模方法(信号注入、数据记录);3)两种扫频方式(逐频正弦/Chirp扫频)的实现;4)MATLAB数据处理(FFT分析、传递函数拟合);5)线性分析工具使用技巧。重点强调了激励信号幅值控制、稳态数据采集及模型验证方法,并提供完整MATLAB脚本示例。该流程可有效获取系统频域特性,为控制器设计提供可靠依据。

Sumerking的博客 233

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

浅析Linux虚拟网络技术

在传统的网络环境中,一台物理主机包含一张或多张网卡,要实现与其它物理主机之间的通信,需要将自身的网卡通过路由器或者交换机连接到外部的物理网络中。随着虚拟化技术的发展,一台物理主机上会部署多个虚拟机或者容器应用,每个虚拟机都需要与物理机,以及主机或者跨主机上的其它虚拟机进行通信,为了实现与传统物理网络等同的虚拟网络结构,各类虚拟网络设备被加入,其中最为核心的两种网络设备就是NIC网卡与交换机设备。

Aspiresky的专栏 799

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

内核阅读之浅析Linux2.6.34内核桥接数据转发(二)

按照内核阅读之浅析Linux2.6.34内核桥接数据转发(一)中的总体框架,依次浅析各个主要关键函数,看看里面具体实现了什么。 首先是int netif_receive_skb()函数,所有从硬件那边上来的数据包都首先要经过这个函数,当然也有例外,目前绝大多数网络芯片厂商都会有硬件加速模块,纯CPU已经无法迎合市场需求了。但是不管怎么说,任何网络数据的第一个包都是要经过netif_receive

Robin_FJ的博客 903

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

上一篇: sdio架构初解
hellolwl
博客等级 码龄24年 16粉丝 0原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值