1 #include <linux/errno.h>
3 #include <linux/kernel.h>
4 #include <linux/module.h>
5 #include <linux/skbuff.h>
6 #include <linux/socket.h>
7 #include <linux/types.h>
8 #include <net/checksum.h>
10 #include <net/ip6_fib.h>
11 #include <net/lwtunnel.h>
12 #include <net/protocol.h>
13 #include <uapi/linux/ila.h>
16 static inline struct ila_params
*ila_params_lwtunnel(
17 struct lwtunnel_state
*lwstate
)
19 return (struct ila_params
*)lwstate
->data
;
22 static int ila_output(struct net
*net
, struct sock
*sk
, struct sk_buff
*skb
)
24 struct dst_entry
*dst
= skb_dst(skb
);
26 if (skb
->protocol
!= htons(ETH_P_IPV6
))
29 update_ipv6_locator(skb
, ila_params_lwtunnel(dst
->lwtstate
));
31 return dst
->lwtstate
->orig_output(net
, sk
, skb
);
38 static int ila_input(struct sk_buff
*skb
)
40 struct dst_entry
*dst
= skb_dst(skb
);
42 if (skb
->protocol
!= htons(ETH_P_IPV6
))
45 update_ipv6_locator(skb
, ila_params_lwtunnel(dst
->lwtstate
));
47 return dst
->lwtstate
->orig_input(skb
);
54 static struct nla_policy ila_nl_policy
[ILA_ATTR_MAX
+ 1] = {
55 [ILA_ATTR_LOCATOR
] = { .type
= NLA_U64
, },
58 static int ila_build_state(struct net_device
*dev
, struct nlattr
*nla
,
59 unsigned int family
, const void *cfg
,
60 struct lwtunnel_state
**ts
)
63 struct nlattr
*tb
[ILA_ATTR_MAX
+ 1];
64 size_t encap_len
= sizeof(*p
);
65 struct lwtunnel_state
*newts
;
66 const struct fib6_config
*cfg6
= cfg
;
69 if (family
!= AF_INET6
)
72 ret
= nla_parse_nested(tb
, ILA_ATTR_MAX
, nla
,
77 if (!tb
[ILA_ATTR_LOCATOR
])
80 newts
= lwtunnel_state_alloc(encap_len
);
84 newts
->len
= encap_len
;
85 p
= ila_params_lwtunnel(newts
);
87 p
->locator
= (__force __be64
)nla_get_u64(tb
[ILA_ATTR_LOCATOR
]);
89 if (cfg6
->fc_dst_len
> sizeof(__be64
)) {
90 /* Precompute checksum difference for translation since we
91 * know both the old locator and the new one.
93 p
->locator_match
= *(__be64
*)&cfg6
->fc_dst
;
94 p
->csum_diff
= compute_csum_diff8(
95 (__be32
*)&p
->locator_match
, (__be32
*)&p
->locator
);
98 newts
->type
= LWTUNNEL_ENCAP_ILA
;
99 newts
->flags
|= LWTUNNEL_STATE_OUTPUT_REDIRECT
|
100 LWTUNNEL_STATE_INPUT_REDIRECT
;
107 static int ila_fill_encap_info(struct sk_buff
*skb
,
108 struct lwtunnel_state
*lwtstate
)
110 struct ila_params
*p
= ila_params_lwtunnel(lwtstate
);
112 if (nla_put_u64(skb
, ILA_ATTR_LOCATOR
, (__force u64
)p
->locator
))
113 goto nla_put_failure
;
121 static int ila_encap_nlsize(struct lwtunnel_state
*lwtstate
)
123 /* No encapsulation overhead */
127 static int ila_encap_cmp(struct lwtunnel_state
*a
, struct lwtunnel_state
*b
)
129 struct ila_params
*a_p
= ila_params_lwtunnel(a
);
130 struct ila_params
*b_p
= ila_params_lwtunnel(b
);
132 return (a_p
->locator
!= b_p
->locator
);
135 static const struct lwtunnel_encap_ops ila_encap_ops
= {
136 .build_state
= ila_build_state
,
137 .output
= ila_output
,
139 .fill_encap
= ila_fill_encap_info
,
140 .get_encap_size
= ila_encap_nlsize
,
141 .cmp_encap
= ila_encap_cmp
,
144 int ila_lwt_init(void)
146 return lwtunnel_encap_add_ops(&ila_encap_ops
, LWTUNNEL_ENCAP_ILA
);
149 void ila_lwt_fini(void)
151 lwtunnel_encap_del_ops(&ila_encap_ops
, LWTUNNEL_ENCAP_ILA
);