~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/ipv6/ila/ila_lwt.c

Version: ~ [ linux-6.3-rc3 ] ~ [ linux-6.2.7 ] ~ [ linux-6.1.20 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.103 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.175 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.237 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.278 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.310 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 #include <linux/errno.h>
  2 #include <linux/ip.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>
  9 #include <net/ip.h>
 10 #include <net/ip6_fib.h>
 11 #include <net/lwtunnel.h>
 12 #include <net/protocol.h>
 13 #include <uapi/linux/ila.h>
 14 #include "ila.h"
 15 
 16 static inline struct ila_params *ila_params_lwtunnel(
 17         struct lwtunnel_state *lwstate)
 18 {
 19         return (struct ila_params *)lwstate->data;
 20 }
 21 
 22 static int ila_output(struct net *net, struct sock *sk, struct sk_buff *skb)
 23 {
 24         struct dst_entry *dst = skb_dst(skb);
 25 
 26         if (skb->protocol != htons(ETH_P_IPV6))
 27                 goto drop;
 28 
 29         ila_update_ipv6_locator(skb, ila_params_lwtunnel(dst->lwtstate));
 30 
 31         return dst->lwtstate->orig_output(net, sk, skb);
 32 
 33 drop:
 34         kfree_skb(skb);
 35         return -EINVAL;
 36 }
 37 
 38 static int ila_input(struct sk_buff *skb)
 39 {
 40         struct dst_entry *dst = skb_dst(skb);
 41 
 42         if (skb->protocol != htons(ETH_P_IPV6))
 43                 goto drop;
 44 
 45         ila_update_ipv6_locator(skb, ila_params_lwtunnel(dst->lwtstate));
 46 
 47         return dst->lwtstate->orig_input(skb);
 48 
 49 drop:
 50         kfree_skb(skb);
 51         return -EINVAL;
 52 }
 53 
 54 static struct nla_policy ila_nl_policy[ILA_ATTR_MAX + 1] = {
 55         [ILA_ATTR_LOCATOR] = { .type = NLA_U64, },
 56         [ILA_ATTR_CSUM_MODE] = { .type = NLA_U8, },
 57 };
 58 
 59 static int ila_build_state(struct net_device *dev, struct nlattr *nla,
 60                            unsigned int family, const void *cfg,
 61                            struct lwtunnel_state **ts)
 62 {
 63         struct ila_params *p;
 64         struct nlattr *tb[ILA_ATTR_MAX + 1];
 65         size_t encap_len = sizeof(*p);
 66         struct lwtunnel_state *newts;
 67         const struct fib6_config *cfg6 = cfg;
 68         struct ila_addr *iaddr;
 69         int ret;
 70 
 71         if (family != AF_INET6)
 72                 return -EINVAL;
 73 
 74         if (cfg6->fc_dst_len < sizeof(struct ila_locator) + 1) {
 75                 /* Need to have full locator and at least type field
 76                  * included in destination
 77                  */
 78                 return -EINVAL;
 79         }
 80 
 81         iaddr = (struct ila_addr *)&cfg6->fc_dst;
 82 
 83         if (!ila_addr_is_ila(iaddr) || ila_csum_neutral_set(iaddr->ident)) {
 84                 /* Don't allow translation for a non-ILA address or checksum
 85                  * neutral flag to be set.
 86                  */
 87                 return -EINVAL;
 88         }
 89 
 90         ret = nla_parse_nested(tb, ILA_ATTR_MAX, nla,
 91                                ila_nl_policy);
 92         if (ret < 0)
 93                 return ret;
 94 
 95         if (!tb[ILA_ATTR_LOCATOR])
 96                 return -EINVAL;
 97 
 98         newts = lwtunnel_state_alloc(encap_len);
 99         if (!newts)
100                 return -ENOMEM;
101 
102         newts->len = encap_len;
103         p = ila_params_lwtunnel(newts);
104 
105         p->locator.v64 = (__force __be64)nla_get_u64(tb[ILA_ATTR_LOCATOR]);
106 
107         /* Precompute checksum difference for translation since we
108          * know both the old locator and the new one.
109          */
110         p->locator_match = iaddr->loc;
111         p->csum_diff = compute_csum_diff8(
112                 (__be32 *)&p->locator_match, (__be32 *)&p->locator);
113 
114         if (tb[ILA_ATTR_CSUM_MODE])
115                 p->csum_mode = nla_get_u8(tb[ILA_ATTR_CSUM_MODE]);
116 
117         ila_init_saved_csum(p);
118 
119         newts->type = LWTUNNEL_ENCAP_ILA;
120         newts->flags |= LWTUNNEL_STATE_OUTPUT_REDIRECT |
121                         LWTUNNEL_STATE_INPUT_REDIRECT;
122 
123         *ts = newts;
124 
125         return 0;
126 }
127 
128 static int ila_fill_encap_info(struct sk_buff *skb,
129                                struct lwtunnel_state *lwtstate)
130 {
131         struct ila_params *p = ila_params_lwtunnel(lwtstate);
132 
133         if (nla_put_u64_64bit(skb, ILA_ATTR_LOCATOR, (__force u64)p->locator.v64,
134                               ILA_ATTR_PAD))
135                 goto nla_put_failure;
136         if (nla_put_u8(skb, ILA_ATTR_CSUM_MODE, (__force u8)p->csum_mode))
137                 goto nla_put_failure;
138 
139         return 0;
140 
141 nla_put_failure:
142         return -EMSGSIZE;
143 }
144 
145 static int ila_encap_nlsize(struct lwtunnel_state *lwtstate)
146 {
147         return nla_total_size_64bit(sizeof(u64)) + /* ILA_ATTR_LOCATOR */
148                nla_total_size(sizeof(u8)) +        /* ILA_ATTR_CSUM_MODE */
149                0;
150 }
151 
152 static int ila_encap_cmp(struct lwtunnel_state *a, struct lwtunnel_state *b)
153 {
154         struct ila_params *a_p = ila_params_lwtunnel(a);
155         struct ila_params *b_p = ila_params_lwtunnel(b);
156 
157         return (a_p->locator.v64 != b_p->locator.v64);
158 }
159 
160 static const struct lwtunnel_encap_ops ila_encap_ops = {
161         .build_state = ila_build_state,
162         .output = ila_output,
163         .input = ila_input,
164         .fill_encap = ila_fill_encap_info,
165         .get_encap_size = ila_encap_nlsize,
166         .cmp_encap = ila_encap_cmp,
167 };
168 
169 int ila_lwt_init(void)
170 {
171         return lwtunnel_encap_add_ops(&ila_encap_ops, LWTUNNEL_ENCAP_ILA);
172 }
173 
174 void ila_lwt_fini(void)
175 {
176         lwtunnel_encap_del_ops(&ila_encap_ops, LWTUNNEL_ENCAP_ILA);
177 }
178 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp