aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/ipip.c
diff options
context:
space:
mode:
authorTom Herbert <therbert@google.com>2014-09-17 15:26:00 -0400
committerDavid S. Miller <davem@davemloft.net>2014-09-19 17:15:32 -0400
commit473ab820dd4af588785a8e10b9c1547aadb4fd72 (patch)
tree478bb4b8987b7cd1f2ad1e0b7d5756ce6b993a94 /net/ipv4/ipip.c
parent14909664e4e192f4c6f6fcdccd9919af7cf783ab (diff)
ipip: Setup and TX path for ipip/UDP foo-over-udp encapsulation
Add netlink handling for IP tunnel encapsulation parameters and and adjustment of MTU for encapsulation. ip_tunnel_encap is called from ip_tunnel_xmit to actually perform FOU encapsulation. Signed-off-by: Tom Herbert <therbert@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/ipip.c')
-rw-r--r--net/ipv4/ipip.c78
1 files changed, 77 insertions, 1 deletions
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 62eaa005e146..bfec31df8b21 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -301,7 +301,8 @@ static int ipip_tunnel_init(struct net_device *dev)
301 memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); 301 memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4);
302 memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); 302 memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4);
303 303
304 tunnel->hlen = 0; 304 tunnel->tun_hlen = 0;
305 tunnel->hlen = tunnel->tun_hlen + tunnel->encap_hlen;
305 tunnel->parms.iph.protocol = IPPROTO_IPIP; 306 tunnel->parms.iph.protocol = IPPROTO_IPIP;
306 return ip_tunnel_init(dev); 307 return ip_tunnel_init(dev);
307} 308}
@@ -340,10 +341,53 @@ static void ipip_netlink_parms(struct nlattr *data[],
340 parms->iph.frag_off = htons(IP_DF); 341 parms->iph.frag_off = htons(IP_DF);
341} 342}
342 343
344/* This function returns true when ENCAP attributes are present in the nl msg */
345static bool ipip_netlink_encap_parms(struct nlattr *data[],
346 struct ip_tunnel_encap *ipencap)
347{
348 bool ret = false;
349
350 memset(ipencap, 0, sizeof(*ipencap));
351
352 if (!data)
353 return ret;
354
355 if (data[IFLA_IPTUN_ENCAP_TYPE]) {
356 ret = true;
357 ipencap->type = nla_get_u16(data[IFLA_IPTUN_ENCAP_TYPE]);
358 }
359
360 if (data[IFLA_IPTUN_ENCAP_FLAGS]) {
361 ret = true;
362 ipencap->flags = nla_get_u16(data[IFLA_IPTUN_ENCAP_FLAGS]);
363 }
364
365 if (data[IFLA_IPTUN_ENCAP_SPORT]) {
366 ret = true;
367 ipencap->sport = nla_get_u16(data[IFLA_IPTUN_ENCAP_SPORT]);
368 }
369
370 if (data[IFLA_IPTUN_ENCAP_DPORT]) {
371 ret = true;
372 ipencap->dport = nla_get_u16(data[IFLA_IPTUN_ENCAP_DPORT]);
373 }
374
375 return ret;
376}
377
343static int ipip_newlink(struct net *src_net, struct net_device *dev, 378static int ipip_newlink(struct net *src_net, struct net_device *dev,
344 struct nlattr *tb[], struct nlattr *data[]) 379 struct nlattr *tb[], struct nlattr *data[])
345{ 380{
346 struct ip_tunnel_parm p; 381 struct ip_tunnel_parm p;
382 struct ip_tunnel_encap ipencap;
383
384 if (ipip_netlink_encap_parms(data, &ipencap)) {
385 struct ip_tunnel *t = netdev_priv(dev);
386 int err = ip_tunnel_encap_setup(t, &ipencap);
387
388 if (err < 0)
389 return err;
390 }
347 391
348 ipip_netlink_parms(data, &p); 392 ipip_netlink_parms(data, &p);
349 return ip_tunnel_newlink(dev, tb, &p); 393 return ip_tunnel_newlink(dev, tb, &p);
@@ -353,6 +397,15 @@ static int ipip_changelink(struct net_device *dev, struct nlattr *tb[],
353 struct nlattr *data[]) 397 struct nlattr *data[])
354{ 398{
355 struct ip_tunnel_parm p; 399 struct ip_tunnel_parm p;
400 struct ip_tunnel_encap ipencap;
401
402 if (ipip_netlink_encap_parms(data, &ipencap)) {
403 struct ip_tunnel *t = netdev_priv(dev);
404 int err = ip_tunnel_encap_setup(t, &ipencap);
405
406 if (err < 0)
407 return err;
408 }
356 409
357 ipip_netlink_parms(data, &p); 410 ipip_netlink_parms(data, &p);
358 411
@@ -378,6 +431,14 @@ static size_t ipip_get_size(const struct net_device *dev)
378 nla_total_size(1) + 431 nla_total_size(1) +
379 /* IFLA_IPTUN_PMTUDISC */ 432 /* IFLA_IPTUN_PMTUDISC */
380 nla_total_size(1) + 433 nla_total_size(1) +
434 /* IFLA_IPTUN_ENCAP_TYPE */
435 nla_total_size(2) +
436 /* IFLA_IPTUN_ENCAP_FLAGS */
437 nla_total_size(2) +
438 /* IFLA_IPTUN_ENCAP_SPORT */
439 nla_total_size(2) +
440 /* IFLA_IPTUN_ENCAP_DPORT */
441 nla_total_size(2) +
381 0; 442 0;
382} 443}
383 444
@@ -394,6 +455,17 @@ static int ipip_fill_info(struct sk_buff *skb, const struct net_device *dev)
394 nla_put_u8(skb, IFLA_IPTUN_PMTUDISC, 455 nla_put_u8(skb, IFLA_IPTUN_PMTUDISC,
395 !!(parm->iph.frag_off & htons(IP_DF)))) 456 !!(parm->iph.frag_off & htons(IP_DF))))
396 goto nla_put_failure; 457 goto nla_put_failure;
458
459 if (nla_put_u16(skb, IFLA_IPTUN_ENCAP_TYPE,
460 tunnel->encap.type) ||
461 nla_put_u16(skb, IFLA_IPTUN_ENCAP_SPORT,
462 tunnel->encap.sport) ||
463 nla_put_u16(skb, IFLA_IPTUN_ENCAP_DPORT,
464 tunnel->encap.dport) ||
465 nla_put_u16(skb, IFLA_IPTUN_ENCAP_FLAGS,
466 tunnel->encap.dport))
467 goto nla_put_failure;
468
397 return 0; 469 return 0;
398 470
399nla_put_failure: 471nla_put_failure:
@@ -407,6 +479,10 @@ static const struct nla_policy ipip_policy[IFLA_IPTUN_MAX + 1] = {
407 [IFLA_IPTUN_TTL] = { .type = NLA_U8 }, 479 [IFLA_IPTUN_TTL] = { .type = NLA_U8 },
408 [IFLA_IPTUN_TOS] = { .type = NLA_U8 }, 480 [IFLA_IPTUN_TOS] = { .type = NLA_U8 },
409 [IFLA_IPTUN_PMTUDISC] = { .type = NLA_U8 }, 481 [IFLA_IPTUN_PMTUDISC] = { .type = NLA_U8 },
482 [IFLA_IPTUN_ENCAP_TYPE] = { .type = NLA_U16 },
483 [IFLA_IPTUN_ENCAP_FLAGS] = { .type = NLA_U16 },
484 [IFLA_IPTUN_ENCAP_SPORT] = { .type = NLA_U16 },
485 [IFLA_IPTUN_ENCAP_DPORT] = { .type = NLA_U16 },
410}; 486};
411 487
412static struct rtnl_link_ops ipip_link_ops __read_mostly = { 488static struct rtnl_link_ops ipip_link_ops __read_mostly = {