协议处理函数

网络协议栈处理整体结构

image 执行正确的协议处理函数

就每种网络协议而言,无论其所在的分层如何,都有一个初始化函数。其中包括L3协议、链路层协议等等。就静态包含在内核中的协议而言,初始化函数会在引导期间执行;就编译成模块的协议而言,当模块加载时,初始化函数就会执行。此函数会分配内部数据结构,通知其他子系统有关该协议的存在,在/proc中注册文件等等。有一项关键任务是在内核注册一个处理函数,以处理该协议的流量。

协议处理函数的组织

 

image

   1:  struct packet_type {
   2:      __be16            type;    /* This is really htons(ether_type). */
   3:      struct net_device    *dev;    /* NULL is wildcarded here         */为NULL时指代所有的设备
   4:      int            (*func) (struct sk_buff *,
   5:                       struct net_device *,
   6:                       struct packet_type *,
   7:                       struct net_device *);
   8:      struct sk_buff        *(*gso_segment)(struct sk_buff *skb,
   9:                          netdev_features_t features);
  10:      int            (*gso_send_check)(struct sk_buff *skb);
  11:      struct sk_buff        **(*gro_receive)(struct sk_buff **head,
  12:                             struct sk_buff *skb);
  13:      int            (*gro_complete)(struct sk_buff *skb);
  14:      void            *af_packet_priv;由PF_PACKET套接字使用,指向于packet_type结构建立相关联的sock数据结构。
  15:      struct list_head    list;冲突消除链表
  16:  };
   1:  void dev_add_pack(struct packet_type *pt)
   2:  {
   3:      struct list_head *head = ptype_head(pt);
   4:   
   5:      spin_lock(&ptype_lock);
   6:      list_add_rcu(&pt->list, head);
   7:      spin_unlock(&ptype_lock);
   8:  }
   9:  EXPORT_SYMBOL(dev_add_pack);
   1:  void __dev_remove_pack(struct packet_type *pt)
   2:  {
   3:      struct list_head *head = ptype_head(pt);
   4:      struct packet_type *pt1;
   5:   
   6:      spin_lock(&ptype_lock);
   7:   
   8:      list_for_each_entry(pt1, head, list) {
   9:          if (pt == pt1) {
  10:              list_del_rcu(&pt->list);
  11:              goto out;
  12:          }
  13:      }
  14:   
  15:      printk(KERN_WARNING "dev_remove_pack: %p not found.\n", pt);
  16:  out:
  17:      spin_unlock(&ptype_lock);
  18:  }
  19:  EXPORT_SYMBOL(__dev_remove_pack);

协议值确定

   1:  /**
   2:   * eth_type_trans - determine the packet's protocol ID.
   3:   * @skb: received socket data
   4:   * @dev: receiving network device
   5:   *
   6:   * The rule here is that we
   7:   * assume 802.3 if the type field is short enough to be a length.
   8:   * This is normal practice and works for any 'now in use' protocol.
   9:   */
  10:  __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev)
  11:  {
  12:      struct ethhdr *eth;
  13:   
  14:      skb->dev = dev;
  15:      skb_reset_mac_header(skb);
  16:      skb_pull_inline(skb, ETH_HLEN);
  17:      eth = eth_hdr(skb);
  18:   
  19:      if (unlikely(is_multicast_ether_addr(eth->h_dest))) {
  20:          if (!compare_ether_addr_64bits(eth->h_dest, dev->broadcast))
  21:              skb->pkt_type = PACKET_BROADCAST;
  22:          else
  23:              skb->pkt_type = PACKET_MULTICAST;
  24:      }
  25:   
  26:      /*
  27:       *      This ALLMULTI check should be redundant by 1.4
  28:       *      so don't forget to remove it.
  29:       *
  30:       *      Seems, you forgot to remove it. All silly devices
  31:       *      seems to set IFF_PROMISC.
  32:       */
  33:   
  34:      else if (1 /*dev->flags&IFF_PROMISC */ ) {
  35:          if (unlikely(compare_ether_addr_64bits(eth->h_dest, dev->dev_addr)))
  36:               = PACKET_OTHERHOST;
  37:      }
  38:   
  39:      /*
  40:       * Some variants of DSA tagging don't have an ethertype field
  41:       * at all, so we check here whether one of those tagging
  42:       * variants has been configured on the receiving interface,
  43:       * and if so, set skb->protocol without looking at the packet.
  44:       */
  45:      if (netdev_uses_dsa_tags(dev))
  46:          return htons(ETH_P_DSA);
  47:      if (netdev_uses_trailer_tags(dev))
  48:          return htons(ETH_P_TRAILER);
  49:   
  50:      
  52:   
  53:      /*
  54:       *      This is a magic hack to spot IPX packets. Older Novell breaks
  55:       *      the protocol design and runs IPX over 802.3 without an 802.2 LLC
  56:       *      layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
  57:       *      won't work for fault tolerant netware but does for the rest.
  58:       */
  59:      if (skb->len >= 2 && *(unsigned short *)(skb->data) == 0xFFFF)
  60:          return htons(ETH_P_802_3);
  61:   
  62:      /*
  63:       *      Real 802.2 LLC
  64:       */
  65:      return htons(ETH_P_802_2);
  66:  }
  67:  EXPORT_SYMBOL(eth_type_trans);

 

image

转载于:https://my.oschina.net/longscu/blog/57714

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值