/* that should never happen */ // 确认我们正在处理的数据包,在二层(L2) 上确实是发往本机的 if (skb->pkt_type != PACKET_HOST) goto drop;
if (unlikely(skb->sk)) goto drop;
if (skb_warn_if_lro(skb)) goto drop;
if (!xfrm4_policy_check(NULL, XFRM_POLICY_FWD, skb)) { SKB_DR_SET(reason, XFRM_POLICY); goto drop; }
// IP 报头中有 Router Alert 选项 // 全局列表 ip_ra_chain,包含了本地套接字列表,都设定了 IP_ROUTER_ALERT 选项 if (IPCB(skb)->opt.router_alert && ip_call_ra_chain(skb)) return NET_RX_SUCCESS;
skb_forward_csum(skb); net = dev_net(skb->dev);
/* * According to the RFC, we must first decrease the TTL field. If * that reaches zero, we must reply an ICMP control message telling * that the packet's lifetime expired. */ if (ip_hdr(skb)->ttl <= 1) goto too_many_hops;
if (!xfrm4_route_forward(skb)) { SKB_DR_SET(reason, XFRM_POLICY); goto drop; }
/* We are about to mangle packet. Copy it! */ if (skb_cow(skb, LL_RESERVED_SPACE(rt->dst.dev)+rt->dst.header_len)) goto drop; iph = ip_hdr(skb);
/* Decrease ttl after skb cow done */ // 递减 TTL, 更新 IP 校验和 ip_decrease_ttl(iph);
/* * We now generate an ICMP HOST REDIRECT giving the route * we calculated. */ if (IPCB(skb)->flags & IPSKB_DOREDIRECT && !opt->srr && !skb_sec_path(skb)) // ICMP REDIRECT ip_rt_send_redirect(skb);
if (READ_ONCE(net->ipv4.sysctl_ip_fwd_update_priority)) skb->priority = rt_tos2priority(iph->tos);