Linux2.6中xfrm框架的dst

Linux内核中ipsec的dst_output处理过程,当执行第一个dst_output时,这时会进入 xfrm4_outpot,下面是这个函数的代码:

int xfrm4_output(struct sk_buff *skb)
{
        return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dst->dev,
                            xfrm4_output_finish,
                            !(IPCB(skb)->flags & IPSKB_REROUTED));
}


static int xfrm4_output_finish(struct sk_buff *skb)
{
        int err;

#ifdef CONFIG_NETFILTER
        if (!skb->dst->xfrm) {
                IPCB(skb)->flags |= IPSKB_REROUTED;
                return dst_output(skb);
        }
#endif
        while (likely((err = xfrm4_output_one(skb)) == 0)) {
                nf_reset(skb);

err = nf_hook(PF_INET, NF_IP_LOCAL_OUT, &skb, NULL,
                              skb->dst->dev, dst_output);
                if (unlikely(err != 1))
                        break;

if (!skb->dst->xfrm)
                        return dst_output(skb);

err = nf_hook(PF_INET, NF_IP_POST_ROUTING, &skb, NULL,
                              skb->dst->dev, xfrm4_output_finish);
                if (unlikely(err != 1))
                        break;
        }

return err;
}

static int xfrm4_output_one(struct sk_buff *skb)
{
        struct dst_entry *dst = skb->dst;
        struct xfrm_state *x = dst->xfrm;
        int err;
      
        if (skb->ip_summed == CHECKSUM_HW) {
                err = skb_checksum_help(skb, 0);
                if (err)
                        goto error_nolock;
        }

if (x->props.mode) {
                err = xfrm4_tunnel_check_size(skb);
                if (err)
                        goto error_nolock;
        }

do {
                spin_lock_bh(&x->lock);
                err = xfrm_state_check(x, skb);
                if (err)
                        goto error;

xfrm4_encap(skb);

err = x->type->output(x, skb);
                if (err)
                        goto error;

x->curlft.bytes += skb->len;
                x->curlft.packets++;

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwjwyd.html