OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [tags/] [linux-2.6/] [linux-2.6.24_or32_unified_v2.3/] [net/] [ipv4/] [xfrm4_mode_tunnel.c] - Blame information for rev 8

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
2
 * xfrm4_mode_tunnel.c - Tunnel mode encapsulation for IPv4.
3
 *
4
 * Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au>
5
 */
6
 
7
#include <linux/init.h>
8
#include <linux/kernel.h>
9
#include <linux/module.h>
10
#include <linux/skbuff.h>
11
#include <linux/stringify.h>
12
#include <net/dst.h>
13
#include <net/inet_ecn.h>
14
#include <net/ip.h>
15
#include <net/xfrm.h>
16
 
17
static inline void ipip_ecn_decapsulate(struct sk_buff *skb)
18
{
19
        struct iphdr *outer_iph = ip_hdr(skb);
20
        struct iphdr *inner_iph = ipip_hdr(skb);
21
 
22
        if (INET_ECN_is_ce(outer_iph->tos))
23
                IP_ECN_set_ce(inner_iph);
24
}
25
 
26
static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb)
27
{
28
        if (INET_ECN_is_ce(iph->tos))
29
                IP6_ECN_set_ce(ipv6_hdr(skb));
30
}
31
 
32
/* Add encapsulation header.
33
 *
34
 * The top IP header will be constructed per RFC 2401.
35
 */
36
static int xfrm4_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
37
{
38
        struct dst_entry *dst = skb->dst;
39
        struct xfrm_dst *xdst = (struct xfrm_dst*)dst;
40
        struct iphdr *iph, *top_iph;
41
        int flags;
42
 
43
        iph = ip_hdr(skb);
44
 
45
        skb_set_network_header(skb, -x->props.header_len);
46
        skb->mac_header = skb->network_header +
47
                          offsetof(struct iphdr, protocol);
48
        skb->transport_header = skb->network_header + sizeof(*iph);
49
        top_iph = ip_hdr(skb);
50
 
51
        top_iph->ihl = 5;
52
        top_iph->version = 4;
53
 
54
        flags = x->props.flags;
55
 
56
        /* DS disclosed */
57
        if (xdst->route->ops->family == AF_INET) {
58
                top_iph->protocol = IPPROTO_IPIP;
59
                top_iph->tos = INET_ECN_encapsulate(iph->tos, iph->tos);
60
                top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ?
61
 
62
        }
63
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
64
        else {
65
                struct ipv6hdr *ipv6h = (struct ipv6hdr*)iph;
66
                top_iph->protocol = IPPROTO_IPV6;
67
                top_iph->tos = INET_ECN_encapsulate(iph->tos, ipv6_get_dsfield(ipv6h));
68
                top_iph->frag_off = 0;
69
        }
70
#endif
71
 
72
        if (flags & XFRM_STATE_NOECN)
73
                IP_ECN_clear(top_iph);
74
 
75
        if (!top_iph->frag_off)
76
                __ip_select_ident(top_iph, dst->child, 0);
77
 
78
        top_iph->ttl = dst_metric(dst->child, RTAX_HOPLIMIT);
79
 
80
        top_iph->saddr = x->props.saddr.a4;
81
        top_iph->daddr = x->id.daddr.a4;
82
 
83
        skb->protocol = htons(ETH_P_IP);
84
 
85
        memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
86
        return 0;
87
}
88
 
89
static int xfrm4_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
90
{
91
        struct iphdr *iph = ip_hdr(skb);
92
        const unsigned char *old_mac;
93
        int err = -EINVAL;
94
 
95
        switch (iph->protocol){
96
                case IPPROTO_IPIP:
97
                        break;
98
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
99
                case IPPROTO_IPV6:
100
                        break;
101
#endif
102
                default:
103
                        goto out;
104
        }
105
 
106
        if (!pskb_may_pull(skb, sizeof(struct iphdr)))
107
                goto out;
108
 
109
        if (skb_cloned(skb) &&
110
            (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
111
                goto out;
112
 
113
        iph = ip_hdr(skb);
114
        if (iph->protocol == IPPROTO_IPIP) {
115
                if (x->props.flags & XFRM_STATE_DECAP_DSCP)
116
                        ipv4_copy_dscp(iph, ipip_hdr(skb));
117
                if (!(x->props.flags & XFRM_STATE_NOECN))
118
                        ipip_ecn_decapsulate(skb);
119
        }
120
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
121
        else {
122
                if (!(x->props.flags & XFRM_STATE_NOECN))
123
                        ipip6_ecn_decapsulate(iph, skb);
124
                skb->protocol = htons(ETH_P_IPV6);
125
        }
126
#endif
127
        old_mac = skb_mac_header(skb);
128
        skb_set_mac_header(skb, -skb->mac_len);
129
        memmove(skb_mac_header(skb), old_mac, skb->mac_len);
130
        skb_reset_network_header(skb);
131
        err = 0;
132
 
133
out:
134
        return err;
135
}
136
 
137
static struct xfrm_mode xfrm4_tunnel_mode = {
138
        .input = xfrm4_tunnel_input,
139
        .output = xfrm4_tunnel_output,
140
        .owner = THIS_MODULE,
141
        .encap = XFRM_MODE_TUNNEL,
142
        .flags = XFRM_MODE_FLAG_TUNNEL,
143
};
144
 
145
static int __init xfrm4_tunnel_init(void)
146
{
147
        return xfrm_register_mode(&xfrm4_tunnel_mode, AF_INET);
148
}
149
 
150
static void __exit xfrm4_tunnel_exit(void)
151
{
152
        int err;
153
 
154
        err = xfrm_unregister_mode(&xfrm4_tunnel_mode, AF_INET);
155
        BUG_ON(err);
156
}
157
 
158
module_init(xfrm4_tunnel_init);
159
module_exit(xfrm4_tunnel_exit);
160
MODULE_LICENSE("GPL");
161
MODULE_ALIAS_XFRM_MODE(AF_INET, XFRM_MODE_TUNNEL);

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.