±¾ÎÄ·ÖÎöÁËlinux 2.4.xÄں˵ÄÍøÇŵÄʵÏÖ·½·¨£¬²¢ÇÒÃèÊöÁËÈçºÎʹÓÃ2.4ÖеÄÍøÇÅ¡£
ÍøÇÅ£¬ÀàËÆÓÚÖÐ¼ÌÆ÷£¬Á¬½Ó¾ÖÓòÍøÖÐÁ½¸ö»òÕß¶à¸öÍø¶Î¡£ËüÓëÖÐ¼ÌÆ÷µÄ²»Í¬Ö®´¦¾ÍÔÚÓÚËüÄܹ»½âÎöËüÊÕ·¢µÄÊý¾Ý£¬¶ÁȡĿ±êµØÖ·ÐÅÏ¢£¨MAC£©£¬²¢¾ö¶¨ÊÇ·ñÏòËùÁ¬½ÓÍøÂçµÄÆäËûÍø¶Îת·¢Êý¾Ý°ü¡£ÎªÁËÄܹ»¾ö²ßÏòÄǸöÍø¶Î·¢ËÍÊý¾Ý°ü£¬ÍøÇÅѧϰ½ÓÊÕµ½Êý¾Ý°üµÄÔ´MACµØÖ·£¬ÔÚ±¾µØ½¨Á¢Ò»¸öÒÔMACºÍ¶Ë¿ÚΪ¼Ç¼ÏîµÄÐÅÏ¢Êý¾Ý¿â¡£
Ò»¡¢LinuxÄÚºËÍøÇŵÄʵÏÖ·ÖÎö
Linux Äں˷ֱðÔÚ2.2 ºÍ 2.4ÄÚºËÖÐʵÏÖÁËÍøÇÅ¡£µ«ÊÇ2.2 ÄÚºËºÍ 2.4Äں˵ÄʵÏÖÓкܴóµÄÇø±ð£¬2.4ÖеÄʵÏÖ¼¸ºõÊÇÈ«²¿ÖØÐ´ÁËËùÓеÄʵÏÖ´úÂë¡£±¾ÎÄÒÔ2.4.0Äں˰汾ΪÀý½øÐзÖÎö¡£
ÔÚ·ÖÎö¾ßÌåµÄʵÏÖ֮ǰ£¬ÏÈÃèÊö¼¸¸ö¸ÅÄÓÐÖúÓÚ¶ÔÍøÇŵŦÄܼ°ÊµÏÖÓиüÉîµÄÀí½â¡£
- ³åÍ»Óò
Ò»¸ö³åÍ»ÓòÓÉËùÓÐÄܹ»¿´µ½Í¬Ò»¸ö³åÍ»»òÕß±»¸Ã³åÍ»Éæ¼°µ½µÄÉ豸×é³É¡£ÒÔÌ«ÍøÊ¹ÓÃC S M A / C D£¨Carrier Sense Multiple Access with Collision Detection£¬´øÓгåÍ»¼à²âµÄÔØ²¨ÕìÌý¶àÖ··ÃÎÊ£©¼¼ÊõÀ´±£Ö¤Í¬Ò»Ê±¿Ì£¬Ö»ÓÐÒ»¸ö½ÚµãÄܹ»ÔÚ³åÍ»ÓòÄÚ´«ËÍÊý¾Ý¡£ÍøÇÅ»òÕß½»»»»ú£¬¹¹³ÉÁËÒ»¸ö³åÍ»ÓòµÄ±ß½ç¡£È±Ê¡Çé¿öÏ£¬ÍøÇÅÖеÄÿ¸ö¶Ë¿Úʵ¼ÊÉϾÍÊÇÒ»¸ö³åÍ»ÓòµÄ½áÊøµã¡£
- ¹ã²¥Óò
Ò»¸ö¹ã²¥ÓòÓÉËùÓÐÄܹ»¿´µ½Ò»¸ö¹ã²¥Êý¾Ý°üµÄÉ豸×é³É¡£Ò»¸ö·ÓÉÆ÷£¬¹¹³ÉÒ»¸ö¹ã²¥ÓòµÄ±ß½ç¡£ÍøÇÅÄܹ»ÑÓÉìµ½µÄ×î´ó·¶Î§¾ÍÊÇÒ»¸ö¹ã²¥Óò¡£È±Ê¡µÄÇé¿öÏ£¬Ò»¸öÍøÇÅ»ò½»»»»úµÄËùÓж˿ÚÔÚͬһ¸ö¹ã²¥ÓòÖС£VLAN¼¼Êõ¿ÉÒ԰ѽ»»»»ú»òÕßÍøÇŵIJ»Í¬¶Ë¿Ú·Ö¸î³É²»Í¬µÄ¹ã²¥Óò¡£Ò»°ãÇé¿öÏ£¬ Ò»¸ö¹ã²¥Óò´ú±íÒ»¸öÂß¼Íø¶Î¡£
- ÍøÇÅÖеÄCAM±í
ÍøÇźͽ»»»»úÒ»Ñù£¬ÎªÁËÄܹ»ÊµÏÖ¶ÔÊý¾Ý°üµÄת·¢£¬ÍøÇű£´æ×ÅÐí¶à£¨MAC£¬¶Ë¿Ú£©Ïî¡£ËùÓеÄÕâЩÏî×é³ÉÒ»¸ö±í£¬½Ð×öCAM±í¡£Ã¿¸öÏîÓг¬Ê±»úÖÆ£¬Èç¹ûÒ»¶¨Ê±¼äÄÚδ½ÓÊÕµ½ÒÔÕâ¸öMACΪԴMACµØÖ·µÄÊý¾Ý°ü£¬Õâ¸öÏî¾Í»á±»É¾³ý¡£

ͼ1£ºÒ»¸ö½»»»ÍøÂçµÄÂ߼ͼ
ÔÚLinuxÄÚºËÍøÇŵÄʵÏÖÖУ¬Ò»¸öÂß¼Íø¶ÎÓÃnet_bridge½á¹¹Ìå±íʾ¡£Ò»¸öÂß¼Íø¶ÎÐèÒª±£ÁôµÄÐÅÏ¢ÓУº
- ±¾Âß¼Íø¶ÎÖÐËùÓеĶ˿Ú(port_list)
ÿ¸ö¶Ë¿ÚÓÃnet_bridge_port½á¹¹ÌåÀ´±íʾ£¬´Ónet_bridge_port½á¹¹ÌåÖпÉÒÔ¿´³ö£¬ËüÖ÷ÒªÓÐ:
- Âß¼Íø¶ÎÖеÄÏÂÒ»¸ö¶Ë¿Ú(next)
- ±¾¶Ë¿ÚËùÊôµÄÂß¼Íø¶Î(br)
- ±¾¶Ë¿ÚËùÖ¸ÏòµÄÎïÀíÍø¿¨£¨dev£©
- ±¾¶Ë¿ÚÔÚÍøÇÅÖеıàºÅ(port_no)
- ÓÃÓÚÉú³ÉÊ÷¹ÜÀíµÄÐÅÏ¢
Ò»¸öÂß¼Íø¶ÎÖпÉÒÔ¾ßÓкܶà¸ö¶Ë¿Ú£¬ËùÓеĶ˿ڶ¼¹ÒÔÚÒÔport_listΪÁ´±íÍ·µÄÁ´±íÉÏ¡£
- ±¾Íø¶ÎÖÐCAM±í£¨hash[BR_HASH_SIZE]£©
CAM±íÖеÄÿ¸öÏîÓÃnet_bridge_fdb_entry½á¹¹Ìå´ú±í£¬Ã¿ÏîÖÐÓУº
- ÓÃÓÚCAM±íÁ¬½ÓµÄÁ´±íÖ¸Õ루next_hash£¬pprev_hash£©
- ´ËÏǰµÄÒýÓüÆÊý£¨use_count£©
- MACµØÖ·£¨addr£©
- ´ËÏîËù¶ÔÓ¦µÄ¶Ë¿Ú£¨dst£©
- ´¦ÀíMAC³¬Ê±£¨ageing_timer£©
- ÊÇ·ñÊDZ¾»úµÄMACµØÖ·£¨is_local£©
- ÊÇ·ñÊǾ²Ì¬MACµØÖ·£¨is_static£©
Ò»¸öÂß¼Íø¶ÎÖеÄËùÓбíÏîÐγÉÒ»¸öCAM±í£¬ËûÃÇÖ®¼äµÄ×éÖ¯¹ØÏµÊÇÒ»¸öHASHÁ´±í¡£HASHÁ´µÄ¸öÊýΪBR_HASH_SIZE£¨256£©¡£
- ±¾Âß¼Íø¶ÎÓÃÓÚºÍÍⲿͨÐŵÄÐéÄâÍøÂçÉ豸£¨dev£©
LinuxÍøÇÅ¿ÉÒÔÔÚÍøÇÅÉÏΪÿ¸öÂß¼Íø¶ÎÅäÖÃÒ»¸öIP£¬ÓÃÓÚºÍÍⲿͨÐÅ¡£Êµ¼ÊÉÏÕâ¸öIP²»ÊÇÅäÖÃÔÚÒ»¸öÌØ¶¨µÄÎïÀíÍø¿¨ÉÏÃæ£¬ ¶øÊǽ¨Á¢Ò»¸öÐéÄâµÄÍø¿¨£¬ÐéÄâÍø¿¨¿ÉÒÔ¸½ÔÚÿ¸öͬһÂß¼Íø¶ÎµÄÎïÀíÍø¿¨ÉÏ£¬ÈÃÕâ¸öÍø¿¨¿ÉÒÔÏóËùÓеÄÎïÀíÍø¿¨Ò»Ñù¹¤×÷¡£´Ó¶øÊ¹ÍøÇÅ¿ÉÒÔºÍÍⲿͨÐÅ¡£
- ±¾Âß¼Íø¶ÎÐéÄâÍø¿¨µÄͳ¼ÆÊý¾Ý£¨statistics£©
°´ÕÕLinuxÍø¿¨Çý¶¯µÄ½Ó¿Ú£¬Ò»¸öÍø¿¨µÄͳ¼ÆÐÅÏ¢ÊÇÓÉÿ¸öÍø¿¨µÄ˽ÓÐÊý¾Ý´¦ÀíµÄ¡£Ò»°ãµÄд·¨ÊÇÓÃdev->privÀ´Ö¸Ïòÿ¸öÍø¿¨µÄͳ¼ÆÊý¾Ý¡£Íø¿¨µÄget_stats·½·¨¾ÍÊÇÓÃÀ´¶Áȡͳ¼ÆÊý¾Ý¡£
- Óû§Ò»¸öÍø¶ÎµÄÉú³ÉÊ÷(STP)ÐÅÏ¢
ÒÔÉ϶Լ¸¸ö½á¹¹ÌåµÄÃèÊöºÍ·ÖÎö¿ÉÒÔͨ¹ýÏÂͼÀ´±íʾ£º

ͼ2£ºLinuxÍøÇÅÊý¾Ý½á¹¹ÃèÊöͼ
ÃèÊöÁËÍøÇŵÄÊý¾Ý½á¹¹ºó£¬¾Í¿ÉÒÔ¿ªÊ¼Êý¾Ý°ü´¦ÀíÁ÷³ÌµÄ·ÖÎö¡£
ÍøÇÅ´¦Àí°ü×ñÑ×ÅÒÔϼ¸ÌõÔÔò£º
- ÔÚÒ»¸ö½Ó¿ÚÉϽÓÊÕµ½µÄ°ü²»»áÔÙÔÚÄǸö½Ó¿ÚÉÏ·¢ËÍÕâ¸öÊý¾Ý°ü¡£
- ÿ¸ö½ÓÊÕµ½µÄÊý¾Ý°ü¶¼ÒªÑ§Ï°ÆäÔ´MACµØÖ·¡£
- Èç¹ûÊý¾Ý°üÊǶಥ°ü»ò¹ã²¥°ü£¬ÔòÒªÔÚͬһ¸öÍø¶ÎÖгýÁ˽ÓÊÕ¶Ë¿ÚÍâµÄÆäËûËùÓж˿ڷ¢ËÍÕâ¸öÊý¾Ý°ü£¬Èç¹ûÉϲãÐÒéÕ»¶Ô¶à²¥°ü¸ÐÐËȤ£¬ÔòÐèÒª°ÑÊý¾Ý°üÌá½»¸øÉϲãÐÒéÕ»¡£
- Èç¹ûÊý¾Ý°üµÄÄ¿µÄMACµØÖ·²»ÄÜÔÚCAM±íÖÐÕÒµ½£¬ÔòÒªÔÚͬһ¸öÍø¶ÎÖгýÁ˽ÓÊÕ¶Ë¿ÚÍâµÄÆäËûËùÓж˿ڷ¢ËÍÕâ¸öÊý¾Ý°ü¡£
- Èç¹ûÄܹ»ÔÚCAM±íÖвéѯµ½Ä¿µÄMACµØÖ·£¬ÔòÔÚÌØ¶¨µÄ¶Ë¿ÚÉÏ·¢ËÍÕâ¸öÊý¾Ý°ü£¬Èç¹û·¢ËͶ˿ںͽÓÊÕ¶Ë¿ÚÊÇͬһ¶Ë¿Ú£¬Ôò²»·¢ËÍ¡£
ÔÚÍøÂçÈíÖжϴ¦Àíº¯Êýnet_rx_actionÖУ¬Ç¶ÈëÁËhandle_bridgeÓÃÓÚ°ÑÊý¾Ý°üskbËÍÈëÍøÇÅÄ£¿é´¦Àí¡£
|
br_handle_frame_hookÊÇÍøÇÅ´¦Àí½ÓÊÕµ½Êý¾Ý°üµÄÖÐÈë¿Ú£¬ÍøÇųõʼ»¯£¨br_init£©µÄʱºò£¬°Ñbr_handle_frame_hook¸³ÖµÎªbr_handle_frame¡£skb->dev->br_portÓÃÓÚÅжϽÓÊÕµ½Õâ¸öÊý¾Ý°üµÄ½Ó¿ÚÊÇ·ñÊÇÍøÇÅÖеÄÒ»¸ö¶Ë¿Ú£¬Èç¹ûÊÇ£¬skb->dev->br_port²»ÎªNULL£¬ÄÇôÊý¾Ý°üÓ¦¸ÃÓÉÍøÇÅ´¦Àí¡£·´Ö®£¬Êý¾Ý°üÓÉÉϲãÐÒéÕ»´¦Àí¡£ÍøÇÅÖÐÐéÄâÍø¿¨¶ÔÓ¦µÄÊý¾Ý°ü¾ÍÊÇÔÚÕâ¸öÅжϵãʱ²»ÔÙ½øÈëÍøÇÅ¡££¨Êµ¼ÊÉÏÐéÄâÍø¿¨²¢²»»á×Ô¼ºÖ÷¶¯½ÓÊÕÊý¾Ý°ü£¬¶øÊÇÔÚÍøÇÅ´¦ÀíÖаÑÊý¾Ý°üÏò±¾µØÉϲãÐÒéÕ»Ìá½»£¬²¢ÇÒÐÞ¸ÄÁËskb->dev£¬Ê¹µÃÊý¾Ý°ü²»»á¶à´Î½øÈëÇÅ´¦Àí´úÂ룩¡£
Ç°ÃæÌáµ½£¬ÍøÇÅ´¦Àí½ÓÊÕ°üµÄÈë¿ÚÊÇbr_handle_frame(net/bridge/br_input.c)º¯Êý¡£
br_handle_frameº¯ÊýÊ×ÏÈ´ÓskbÖлñµÃÕâ¸ö°üÊôÓÚµÄÂß¼Íø¶Î¡£È»ºóµ÷ÓÃ__br_handle_frame½øÐÐת·¢´¦Àí¡£ br_handle_frameº¯ÊýÀïÓÐÒ»¸öÖµµÃÁ˽âµÄµØ·½£¬ÀïÃæÓÐÒ»¸ö¼Ó¶ÁËø¡£ÒòΪÔÚת·¢ÖÐÐèÒª¶ÁCAM±í£¬ËùÒÔ±ØÐë¼Ó¶ÁËø£¬±ÜÃâÔÚÕâ¸ö¹ý³ÌÖÐÁíÍâµÄÄں˿ØÖÆÂ·¾¶(Èç¶à´¦Àí»úÉÏÁíÍâÒ»¸öCPUÉϵÄϵͳµ÷ÓÃ)ÐÞ¸ÄCAM±í¡£
¶ÔÊäÈë°üµÄת·¢¾ö²ß¶¼ÊÇÔÚ__br_handle_frameº¯ÊýÖС£Õâ¸öº¯ÊýµÄ´¦Àí¿ÉÒÔ·ÖΪÒÔϼ¸¸ö²¿·Ö£º
- Èç¹ûÍøÇŵÄÐéÄâÍø¿¨´¦ÓÚ»ìÔÓģʽ£¬ÄÇôÿ¸ö½ÓÊÕµ½µÄÊý¾Ý°ü¶¼ÐèÒª¿Ë¡һ·ÝË͵½AF_PACKETÐÒé´¦ÀíÌå(ÍøÂçÈíÖжϺ¯Êýnet_rx_actionÖÐptype_allÁ´µÄ´¦Àí)¡£
if (br->dev.flags & IFF_PROMISC) { struct sk_buff *skb2; skb2 = skb_clone(skb, GFP_ATOMIC); if (skb2) { passedup = 1; br_pass_frame_up(br, skb2); } }
- Èç¹ûÔ´MACµØÖ·ÊǶಥ»òÕßÊǹ㲥µØÖ·£¬ÄÇôÕâ¸ö°ü¸ñʽÊÇ´íÎóµÄ£¬¼òµ¥µÄ¶ªÆú¡£
if (skb->mac.ethernet->h_source[0] & 1) goto freeandout;
- Èç¹ûÊÇÒ»¸ö¶à²¥°ü£¬ÔòÐèÒªÏò±¾»úµÄÉϲãÐÒéÕ»´«ËÍÕâ¸öÊý¾Ý°ü£¨Èç¹ûÔÚ֮ǰûÓÐÏòÉÏÌá½»µÄ»°£¬¼´passedupΪ0¡£Èç¹ûΪ1£¬ÔòÇ°ÃæÒѾ·¢ËÍÁË£¬ÏÖÔھͲ»ÐèÒªÌá½»ÁË£¬ÔÚºóÃæÖеĴ¦Àí¶¼ÊÇÒ»ÑùµÄ£©¡£
if (!passedup && (dest[0] & 1) && (br->dev.flags & IFF_ALLMULTI || br->dev.mc_list != NULL)) { struct sk_buff *skb2; skb2 = skb_clone(skb, GFP_ATOMIC); if (skb2) { passedup = 1; br_pass_frame_up(br, skb2); } }
- Èç¹ûÆô¶¯ÁËÉú³ÉÊ÷ÐÒ飬һ¸öÉú³ÉÊ÷°üÐèÒªÓÉÉú³ÉÊ÷ÐÒé´¦ÀíÄ£¿éµ¥¶À´¦Àí¡£Èç¹û²»Ö§³Ö£¬ÔòÕâ¸ö°üµÄÄ¿µÄMAC¿Ï¶¨ÔÚCAMÖвéѯ²»µ½£¬ËùÒÔÊÇÏòËùÓеĶ˿ڷ¢ËÍ£¨³ý½ÓÊÕ¿Ú£©¡£ÕâÑù²Å²»»áÓ°ÏìÕû¸öÍøÂçµÄÉú³ÉÊ÷ÐÒéÔËÐС£
if (br->stp_enabled && !memcmp(dest, bridge_ula, 5) && !(dest[5] & 0xF0)) goto handle_special_frame;
- Èç¹û½ÓÊն˿ڲ»ÊÇ´¦ÓÚLEARNING»òÕßFORWARDING£¬ÄÇô¾ÍѧϰÕâ¸ö°üµÄÔ´MACµØÖ·£¬»òÕ߸üÐÂCAM±íÖÐÏàÓ¦ÏîµÄ¶¨Ê±Æ÷¡£
if (p->state == BR_STATE_LEARNING || p->state == BR_STATE_FORWARDING) br_fdb_insert(br, p, skb->mac.ethernet->h_source, 0);
- Èç¹ûÊÇÒ»¸ö¶à²¥°ü»ò¹ã²¥°ü£¬Ôòµ÷ÓÃbr_floodº¯ÊýÏòÿ¸ö¿Ú·¢ËÍ£¨³ý½ÓÊÕ¿Ú£©Õâ¸öÊý¾Ý°ü¡£Èç¹û֮ǰûÓÐÌá½»ÉϲãÐÒ飬ÔòÐèÒª¿Ë¡һ¸ö°üÌá½»ÉϲãÐÒé¡£
if (dest[0] & 1) { br_flood(br, skb, 1); if (!passedup) br_pass_frame_up(br, skb); else kfree_skb(skb); return; }
- ÓýÓÊÕµ½Êý¾Ý°üµÄÄ¿µÄMACµØÖ·²éѯCAM±í¡£
dst = br_fdb_get(br, dest);
- ²éѯCAM±íºó£¬Èç¹ûÄܹ»ÕÒµ½±íÏ²¢ÇÒÄ¿µÄMACÊǵ½±¾»úµÄÐéÄâÍø¿¨µÄ£¬ÄÇô¾ÍÐèÒª°ÑÕâ¸ö°üÌá½»¸øÉϲãÐÒé¡£ÍøÇžÍÊÇͨ¹ýÕâ¸öµØ·½µÄ´¦ÀíºÍÍⲿͨÐÅ£¬ÊµÏÖÔ¶³Ì¹ÜÀíµÄÄ¿µÄ¡£
if (dst != NULL && dst->is_local) { if (!passedup) br_pass_frame_up(br, skb); else kfree_skb(skb); br_fdb_put(dst); return; }
- Èç¹û²éѯCAM±íÓнá¹û£¬²¢ÇÒÄ¿µÄMAC²»Êǵ½±¾µØµÄ£¬ÄÇô¾Íͨ¹ýµ÷ÓÃbr_forward·¢Ë͵½Ìض¨µÄ¶Ë¿Ú¡£
if (dst != NULL) { br_forward(dst->dst, skb); br_fdb_put(dst); return; }
- Èç¹ûÔÚCAM±íÖвéѯ²»µ½Êý¾Ý°üµÄÄ¿µÄMACµØÖ·£¬ÄÇô¾ÍÐèÒªÏò±ðµÄÿ¸ö¶Ë¿Ú·¢ËÍÕâ¸öÊý¾Ý°ü¡£µ÷ÓÃbr_floodÀ´½øÐÐÕâ¸ö´¦Àí¡£
br_flood(br, skb, 0); return;
ÔÚbr_forwardºÍbr_floodº¯ÊýÖж¼±ØÐëÅжÏÔ´½Ó¿ÚºÍÄ¿µÄ½Ó¿ÚÊÇ·ñÊÇͬһ¸ö£¬Èç¹ûÊÇͬһ¶Ë¿Ú£¬¾Í²»·¢ËÍÕâ¸








