-
IPv4协议pkt_type注册
- ipv4_init时调用netif_register_pkt注册
static struct pkt_type ip4_pkt_type = { //.type = rte_cpu_to_be_16(ETHER_TYPE_IPv4), .func = ipv4_rcv, .port = NULL, }; int ipv4_init(void) { int err, i; ip4_idents = rte_malloc(NULL, IP4_IDENTS_SZ * sizeof(*ip4_idents), RTE_CACHE_LINE_SIZE); if (!ip4_idents) return EDPVS_NOMEM; ip4_id_hashrnd = (uint32_t)random(); for (i = 0; i < IP4_IDENTS_SZ; i++) rte_atomic32_set(&ip4_idents[i], (uint32_t)random()); rte_spinlock_init(&inet_prot_lock); rte_spinlock_lock(&inet_prot_lock); for (i = 0; i < NELEMS(inet_prots); i++) inet_prots[i] = NULL; rte_spinlock_unlock(&inet_prot_lock); #ifdef CONFIG_DPVS_IPV4_STATS rte_spinlock_init(&ip4_stats_lock); #endif if ((err = ipv4_frag_init()) != EDPVS_OK) return err; ip4_pkt_type.type = htons(ETHER_TYPE_IPv4); if ((err = netif_register_pkt(&ip4_pkt_type)) != EDPVS_OK) { ipv4_frag_term(); return err; } return EDPVS_OK; }
-
ipv4_rcv
- IPv4三层入口处理函数
- 此时mbuf->data_off已经指向ipv4_hdr起始地址
static int ipv4_rcv(struct rte_mbuf *mbuf, struct netif_port *port) { struct ipv4_hdr *iph; uint16_t hlen, len; eth_type_t etype = mbuf->packet_type; /* FIXME: use other field ? */ assert(mbuf); //二层包类型不是传递至本机数据报,或者net_device设备不存在,释放数据包 if (unlikely(etype == ETH_PKT_OTHERHOST || !port)) { rte_pktmbuf_free(mbuf); return EDPVS_DROP; } //更新统计数据 IP4_UPD_PO_STATS(in, mbuf->pkt_len); iftraf_pkt_in(AF_INET, mbuf, port); //数据报长度校验 if (mbuf_may_pull(mbuf, sizeof(struct ipv4_hdr)) != 0) goto inhdr_error; //获取ipv4包头 iph = ip4_hdr(mbuf); //获取ipv4包头总长度,包括ip选项 hlen = ip4_hdrlen(mbuf); //ip数据包有效性验证,version是ipv4,并且总长度不能小于20字节 if (((iph->version_ihl) >> 4) != 4 || hlen < sizeof(struct ipv4_hdr)) goto inhdr_error; //ip数据包长度验证 if (mbuf_may_pull(mbuf, hlen) != 0) goto inhdr_error; //checksum验证 if (unlikely(!(port->flag & NETIF_PORT_FLAG_RX_IP_CSUM_OFFLOAD))) { if (unlikely(rte_raw_cksum(iph, hlen) != 0xFFFF)) goto csum_error; } //获取ip数据报总长度 len = ntohs(iph->total_length); //如果mbuf的长度小于ipv4数据报总长度,则数据包可能被截断了,终止处理 if (mbuf->pkt_len < len) { IP4_INC_STATS(intruncatedpkts); goto drop; } else if (len < hlen){ //如果数据报总长度小于IPv4数据包头部长度,出错 goto inhdr_error; } /* trim padding if needed */ //如果mbuf总长度大于ip数据报长度,则需要截断后面补充字节,Ethernet中最小帧长度为68,如果不足的话会在后面补充一些数据 if (mbuf->pkt_len > len) { if (rte_pktmbuf_trim(mbuf, mbuf->pkt_len - len) != 0) { IP4_INC_STATS(indiscards); goto drop; } } mbuf->userdata = NULL; //设置mbuf L3层长度 mbuf->l3_len = hlen; #ifdef CONFIG_DPVS_IP_HEADER_DEBUG ip4_show_hdr(__func__, mbuf); #endif /** * 如果L4层协议为OSPF,传递至协议栈处理 * OSPF(Open Shortest Path First开放式最短路径优先)是一个内部网关协议(Interior Gateway Protocol,简称IGP), * 用于在单一自治系统(autonomous system,AS)内决策路由。是对链路状态路由协议的一种实现,隶属内部网关协议(IGP), * 故运作于自治系统内部 */ if (unlikely(iph->next_proto_id == IPPROTO_OSPF)) return EDPVS_KNICONTINUE; //最后调用 INET_HOOK(INET_HOOK_PRE_ROUTING, mbuf, port, NULL, ipv4_rcv_fin) 先调用 INET_HOOK_PRE_ROUTING 这个钩子所 //注册的回调,然后根据返回值判断是否走 ipv4_rcv_fin,不同转发模式行为是不同的 return INET_HOOK(AF_INET, INET_HOOK_PRE_ROUTING, mbuf, port, NULL, ipv4_rcv_fin); csum_error: IP4_INC_STATS(csumerrors); inhdr_error: IP4_INC_STATS(inhdrerrors); drop: rte_pktmbuf_free(mbuf); return EDPVS_INVPKT; }
08-26
947
![](https://csdnimg.cn/release/blogv2/dist/pc/img/readCountWhite.png)
“相关推荐”对你有帮助么?
-
非常没帮助
-
没帮助
-
一般
-
有帮助
-
非常有帮助
提交