aboutsummaryrefslogtreecommitdiffstats
path: root/net/openvswitch
diff options
context:
space:
mode:
authorJiri Benc <jbenc@redhat.com>2015-10-05 07:09:47 -0400
committerDavid S. Miller <davem@davemloft.net>2015-10-07 07:18:00 -0400
commit6b26ba3a7d952e611dcde1f3f77ce63bcc70540a (patch)
tree6c15c6b572dd2656ddd6401549b1cfbb4ecf1931 /net/openvswitch
parent00a93babd06aaad31d23384cda576ede0f586a8c (diff)
openvswitch: netlink attributes for IPv6 tunneling
Add netlink attributes for IPv6 tunnel addresses. This enables IPv6 support for tunnels. Signed-off-by: Jiri Benc <jbenc@redhat.com> Acked-by: Pravin B Shelar <pshelar@nicira.com> Acked-by: Thomas Graf <tgraf@suug.ch> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/openvswitch')
-rw-r--r--net/openvswitch/flow_netlink.c121
1 files changed, 84 insertions, 37 deletions
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index 6be701f6b31b..77850f177a47 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -262,8 +262,8 @@ size_t ovs_tun_key_attr_size(void)
262 * updating this function. 262 * updating this function.
263 */ 263 */
264 return nla_total_size(8) /* OVS_TUNNEL_KEY_ATTR_ID */ 264 return nla_total_size(8) /* OVS_TUNNEL_KEY_ATTR_ID */
265 + nla_total_size(4) /* OVS_TUNNEL_KEY_ATTR_IPV4_SRC */ 265 + nla_total_size(16) /* OVS_TUNNEL_KEY_ATTR_IPV[46]_SRC */
266 + nla_total_size(4) /* OVS_TUNNEL_KEY_ATTR_IPV4_DST */ 266 + nla_total_size(16) /* OVS_TUNNEL_KEY_ATTR_IPV[46]_DST */
267 + nla_total_size(1) /* OVS_TUNNEL_KEY_ATTR_TOS */ 267 + nla_total_size(1) /* OVS_TUNNEL_KEY_ATTR_TOS */
268 + nla_total_size(1) /* OVS_TUNNEL_KEY_ATTR_TTL */ 268 + nla_total_size(1) /* OVS_TUNNEL_KEY_ATTR_TTL */
269 + nla_total_size(0) /* OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT */ 269 + nla_total_size(0) /* OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT */
@@ -323,6 +323,8 @@ static const struct ovs_len_tbl ovs_tunnel_key_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1]
323 [OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS] = { .len = OVS_ATTR_VARIABLE }, 323 [OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS] = { .len = OVS_ATTR_VARIABLE },
324 [OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS] = { .len = OVS_ATTR_NESTED, 324 [OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS] = { .len = OVS_ATTR_NESTED,
325 .next = ovs_vxlan_ext_key_lens }, 325 .next = ovs_vxlan_ext_key_lens },
326 [OVS_TUNNEL_KEY_ATTR_IPV6_SRC] = { .len = sizeof(struct in6_addr) },
327 [OVS_TUNNEL_KEY_ATTR_IPV6_DST] = { .len = sizeof(struct in6_addr) },
326}; 328};
327 329
328/* The size of the argument for each %OVS_KEY_ATTR_* Netlink attribute. */ 330/* The size of the argument for each %OVS_KEY_ATTR_* Netlink attribute. */
@@ -542,14 +544,14 @@ static int vxlan_tun_opt_from_nlattr(const struct nlattr *attr,
542 return 0; 544 return 0;
543} 545}
544 546
545static int ipv4_tun_from_nlattr(const struct nlattr *attr, 547static int ip_tun_from_nlattr(const struct nlattr *attr,
546 struct sw_flow_match *match, bool is_mask, 548 struct sw_flow_match *match, bool is_mask,
547 bool log) 549 bool log)
548{ 550{
549 struct nlattr *a; 551 struct nlattr *a;
550 int rem; 552 int rem;
551 bool ttl = false; 553 bool ttl = false;
552 __be16 tun_flags = 0; 554 __be16 tun_flags = 0, ipv4 = false, ipv6 = false;
553 int opts_type = 0; 555 int opts_type = 0;
554 556
555 nla_for_each_nested(a, attr, rem) { 557 nla_for_each_nested(a, attr, rem) {
@@ -578,10 +580,22 @@ static int ipv4_tun_from_nlattr(const struct nlattr *attr,
578 case OVS_TUNNEL_KEY_ATTR_IPV4_SRC: 580 case OVS_TUNNEL_KEY_ATTR_IPV4_SRC:
579 SW_FLOW_KEY_PUT(match, tun_key.u.ipv4.src, 581 SW_FLOW_KEY_PUT(match, tun_key.u.ipv4.src,
580 nla_get_in_addr(a), is_mask); 582 nla_get_in_addr(a), is_mask);
583 ipv4 = true;
581 break; 584 break;
582 case OVS_TUNNEL_KEY_ATTR_IPV4_DST: 585 case OVS_TUNNEL_KEY_ATTR_IPV4_DST:
583 SW_FLOW_KEY_PUT(match, tun_key.u.ipv4.dst, 586 SW_FLOW_KEY_PUT(match, tun_key.u.ipv4.dst,
584 nla_get_in_addr(a), is_mask); 587 nla_get_in_addr(a), is_mask);
588 ipv4 = true;
589 break;
590 case OVS_TUNNEL_KEY_ATTR_IPV6_SRC:
591 SW_FLOW_KEY_PUT(match, tun_key.u.ipv6.dst,
592 nla_get_in6_addr(a), is_mask);
593 ipv6 = true;
594 break;
595 case OVS_TUNNEL_KEY_ATTR_IPV6_DST:
596 SW_FLOW_KEY_PUT(match, tun_key.u.ipv6.dst,
597 nla_get_in6_addr(a), is_mask);
598 ipv6 = true;
585 break; 599 break;
586 case OVS_TUNNEL_KEY_ATTR_TOS: 600 case OVS_TUNNEL_KEY_ATTR_TOS:
587 SW_FLOW_KEY_PUT(match, tun_key.tos, 601 SW_FLOW_KEY_PUT(match, tun_key.tos,
@@ -636,7 +650,7 @@ static int ipv4_tun_from_nlattr(const struct nlattr *attr,
636 opts_type = type; 650 opts_type = type;
637 break; 651 break;
638 default: 652 default:
639 OVS_NLERR(log, "Unknown IPv4 tunnel attribute %d", 653 OVS_NLERR(log, "Unknown IP tunnel attribute %d",
640 type); 654 type);
641 return -EINVAL; 655 return -EINVAL;
642 } 656 }
@@ -646,22 +660,36 @@ static int ipv4_tun_from_nlattr(const struct nlattr *attr,
646 if (is_mask) 660 if (is_mask)
647 SW_FLOW_KEY_MEMSET_FIELD(match, tun_proto, 0xff, true); 661 SW_FLOW_KEY_MEMSET_FIELD(match, tun_proto, 0xff, true);
648 else 662 else
649 SW_FLOW_KEY_PUT(match, tun_proto, AF_INET, false); 663 SW_FLOW_KEY_PUT(match, tun_proto, ipv6 ? AF_INET6 : AF_INET,
664 false);
650 665
651 if (rem > 0) { 666 if (rem > 0) {
652 OVS_NLERR(log, "IPv4 tunnel attribute has %d unknown bytes.", 667 OVS_NLERR(log, "IP tunnel attribute has %d unknown bytes.",
653 rem); 668 rem);
654 return -EINVAL; 669 return -EINVAL;
655 } 670 }
656 671
672 if (ipv4 && ipv6) {
673 OVS_NLERR(log, "Mixed IPv4 and IPv6 tunnel attributes");
674 return -EINVAL;
675 }
676
657 if (!is_mask) { 677 if (!is_mask) {
658 if (!match->key->tun_key.u.ipv4.dst) { 678 if (!ipv4 && !ipv6) {
679 OVS_NLERR(log, "IP tunnel dst address not specified");
680 return -EINVAL;
681 }
682 if (ipv4 && !match->key->tun_key.u.ipv4.dst) {
659 OVS_NLERR(log, "IPv4 tunnel dst address is zero"); 683 OVS_NLERR(log, "IPv4 tunnel dst address is zero");
660 return -EINVAL; 684 return -EINVAL;
661 } 685 }
686 if (ipv6 && ipv6_addr_any(&match->key->tun_key.u.ipv6.dst)) {
687 OVS_NLERR(log, "IPv6 tunnel dst address is zero");
688 return -EINVAL;
689 }
662 690
663 if (!ttl) { 691 if (!ttl) {
664 OVS_NLERR(log, "IPv4 tunnel TTL not specified."); 692 OVS_NLERR(log, "IP tunnel TTL not specified.");
665 return -EINVAL; 693 return -EINVAL;
666 } 694 }
667 } 695 }
@@ -686,21 +714,36 @@ static int vxlan_opt_to_nlattr(struct sk_buff *skb,
686 return 0; 714 return 0;
687} 715}
688 716
689static int __ipv4_tun_to_nlattr(struct sk_buff *skb, 717static int __ip_tun_to_nlattr(struct sk_buff *skb,
690 const struct ip_tunnel_key *output, 718 const struct ip_tunnel_key *output,
691 const void *tun_opts, int swkey_tun_opts_len) 719 const void *tun_opts, int swkey_tun_opts_len,
720 unsigned short tun_proto)
692{ 721{
693 if (output->tun_flags & TUNNEL_KEY && 722 if (output->tun_flags & TUNNEL_KEY &&
694 nla_put_be64(skb, OVS_TUNNEL_KEY_ATTR_ID, output->tun_id)) 723 nla_put_be64(skb, OVS_TUNNEL_KEY_ATTR_ID, output->tun_id))
695 return -EMSGSIZE; 724 return -EMSGSIZE;
696 if (output->u.ipv4.src && 725 switch (tun_proto) {
697 nla_put_in_addr(skb, OVS_TUNNEL_KEY_ATTR_IPV4_SRC, 726 case AF_INET:
698 output->u.ipv4.src)) 727 if (output->u.ipv4.src &&
699 return -EMSGSIZE; 728 nla_put_in_addr(skb, OVS_TUNNEL_KEY_ATTR_IPV4_SRC,
700 if (output->u.ipv4.dst && 729 output->u.ipv4.src))
701 nla_put_in_addr(skb, OVS_TUNNEL_KEY_ATTR_IPV4_DST, 730 return -EMSGSIZE;
702 output->u.ipv4.dst)) 731 if (output->u.ipv4.dst &&
703 return -EMSGSIZE; 732 nla_put_in_addr(skb, OVS_TUNNEL_KEY_ATTR_IPV4_DST,
733 output->u.ipv4.dst))
734 return -EMSGSIZE;
735 break;
736 case AF_INET6:
737 if (!ipv6_addr_any(&output->u.ipv6.src) &&
738 nla_put_in6_addr(skb, OVS_TUNNEL_KEY_ATTR_IPV6_SRC,
739 &output->u.ipv6.src))
740 return -EMSGSIZE;
741 if (!ipv6_addr_any(&output->u.ipv6.dst) &&
742 nla_put_in6_addr(skb, OVS_TUNNEL_KEY_ATTR_IPV6_DST,
743 &output->u.ipv6.dst))
744 return -EMSGSIZE;
745 break;
746 }
704 if (output->tos && 747 if (output->tos &&
705 nla_put_u8(skb, OVS_TUNNEL_KEY_ATTR_TOS, output->tos)) 748 nla_put_u8(skb, OVS_TUNNEL_KEY_ATTR_TOS, output->tos))
706 return -EMSGSIZE; 749 return -EMSGSIZE;
@@ -734,9 +777,10 @@ static int __ipv4_tun_to_nlattr(struct sk_buff *skb,
734 return 0; 777 return 0;
735} 778}
736 779
737static int ipv4_tun_to_nlattr(struct sk_buff *skb, 780static int ip_tun_to_nlattr(struct sk_buff *skb,
738 const struct ip_tunnel_key *output, 781 const struct ip_tunnel_key *output,
739 const void *tun_opts, int swkey_tun_opts_len) 782 const void *tun_opts, int swkey_tun_opts_len,
783 unsigned short tun_proto)
740{ 784{
741 struct nlattr *nla; 785 struct nlattr *nla;
742 int err; 786 int err;
@@ -745,7 +789,8 @@ static int ipv4_tun_to_nlattr(struct sk_buff *skb,
745 if (!nla) 789 if (!nla)
746 return -EMSGSIZE; 790 return -EMSGSIZE;
747 791
748 err = __ipv4_tun_to_nlattr(skb, output, tun_opts, swkey_tun_opts_len); 792 err = __ip_tun_to_nlattr(skb, output, tun_opts, swkey_tun_opts_len,
793 tun_proto);
749 if (err) 794 if (err)
750 return err; 795 return err;
751 796
@@ -757,9 +802,10 @@ int ovs_nla_put_egress_tunnel_key(struct sk_buff *skb,
757 const struct ip_tunnel_info *egress_tun_info, 802 const struct ip_tunnel_info *egress_tun_info,
758 const void *egress_tun_opts) 803 const void *egress_tun_opts)
759{ 804{
760 return __ipv4_tun_to_nlattr(skb, &egress_tun_info->key, 805 return __ip_tun_to_nlattr(skb, &egress_tun_info->key,
761 egress_tun_opts, 806 egress_tun_opts,
762 egress_tun_info->options_len); 807 egress_tun_info->options_len,
808 ip_tunnel_info_af(egress_tun_info));
763} 809}
764 810
765static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match, 811static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
@@ -810,8 +856,8 @@ static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match,
810 *attrs &= ~(1 << OVS_KEY_ATTR_SKB_MARK); 856 *attrs &= ~(1 << OVS_KEY_ATTR_SKB_MARK);
811 } 857 }
812 if (*attrs & (1 << OVS_KEY_ATTR_TUNNEL)) { 858 if (*attrs & (1 << OVS_KEY_ATTR_TUNNEL)) {
813 if (ipv4_tun_from_nlattr(a[OVS_KEY_ATTR_TUNNEL], match, 859 if (ip_tun_from_nlattr(a[OVS_KEY_ATTR_TUNNEL], match,
814 is_mask, log) < 0) 860 is_mask, log) < 0)
815 return -EINVAL; 861 return -EINVAL;
816 *attrs &= ~(1 << OVS_KEY_ATTR_TUNNEL); 862 *attrs &= ~(1 << OVS_KEY_ATTR_TUNNEL);
817 } 863 }
@@ -1377,8 +1423,8 @@ static int __ovs_nla_put_key(const struct sw_flow_key *swkey,
1377 if (output->tun_key.tun_flags & TUNNEL_OPTIONS_PRESENT) 1423 if (output->tun_key.tun_flags & TUNNEL_OPTIONS_PRESENT)
1378 opts = TUN_METADATA_OPTS(output, swkey->tun_opts_len); 1424 opts = TUN_METADATA_OPTS(output, swkey->tun_opts_len);
1379 1425
1380 if (ipv4_tun_to_nlattr(skb, &output->tun_key, opts, 1426 if (ip_tun_to_nlattr(skb, &output->tun_key, opts,
1381 swkey->tun_opts_len)) 1427 swkey->tun_opts_len, swkey->tun_proto))
1382 goto nla_put_failure; 1428 goto nla_put_failure;
1383 } 1429 }
1384 1430
@@ -1881,7 +1927,7 @@ static int validate_and_copy_set_tun(const struct nlattr *attr,
1881 int err = 0, start, opts_type; 1927 int err = 0, start, opts_type;
1882 1928
1883 ovs_match_init(&match, &key, NULL); 1929 ovs_match_init(&match, &key, NULL);
1884 opts_type = ipv4_tun_from_nlattr(nla_data(attr), &match, false, log); 1930 opts_type = ip_tun_from_nlattr(nla_data(attr), &match, false, log);
1885 if (opts_type < 0) 1931 if (opts_type < 0)
1886 return opts_type; 1932 return opts_type;
1887 1933
@@ -2380,10 +2426,11 @@ static int set_action_to_attr(const struct nlattr *a, struct sk_buff *skb)
2380 if (!start) 2426 if (!start)
2381 return -EMSGSIZE; 2427 return -EMSGSIZE;
2382 2428
2383 err = ipv4_tun_to_nlattr(skb, &tun_info->key, 2429 err = ip_tun_to_nlattr(skb, &tun_info->key,
2384 tun_info->options_len ? 2430 tun_info->options_len ?
2385 ip_tunnel_info_opts(tun_info) : NULL, 2431 ip_tunnel_info_opts(tun_info) : NULL,
2386 tun_info->options_len); 2432 tun_info->options_len,
2433 ip_tunnel_info_af(tun_info));
2387 if (err) 2434 if (err)
2388 return err; 2435 return err;
2389 nla_nest_end(skb, start); 2436 nla_nest_end(skb, start);