aboutsummaryrefslogtreecommitdiffstats
path: root/net/openvswitch/datapath.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/openvswitch/datapath.c')
-rw-r--r--net/openvswitch/datapath.c78
1 files changed, 75 insertions, 3 deletions
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index f14816b80b80..bbd310646bc8 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -362,6 +362,14 @@ static int queue_gso_packets(struct net *net, int dp_ifindex,
362static size_t key_attr_size(void) 362static size_t key_attr_size(void)
363{ 363{
364 return nla_total_size(4) /* OVS_KEY_ATTR_PRIORITY */ 364 return nla_total_size(4) /* OVS_KEY_ATTR_PRIORITY */
365 + nla_total_size(0) /* OVS_KEY_ATTR_TUNNEL */
366 + nla_total_size(8) /* OVS_TUNNEL_KEY_ATTR_ID */
367 + nla_total_size(4) /* OVS_TUNNEL_KEY_ATTR_IPV4_SRC */
368 + nla_total_size(4) /* OVS_TUNNEL_KEY_ATTR_IPV4_DST */
369 + nla_total_size(1) /* OVS_TUNNEL_KEY_ATTR_TOS */
370 + nla_total_size(1) /* OVS_TUNNEL_KEY_ATTR_TTL */
371 + nla_total_size(0) /* OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT */
372 + nla_total_size(0) /* OVS_TUNNEL_KEY_ATTR_CSUM */
365 + nla_total_size(4) /* OVS_KEY_ATTR_IN_PORT */ 373 + nla_total_size(4) /* OVS_KEY_ATTR_IN_PORT */
366 + nla_total_size(4) /* OVS_KEY_ATTR_SKB_MARK */ 374 + nla_total_size(4) /* OVS_KEY_ATTR_SKB_MARK */
367 + nla_total_size(12) /* OVS_KEY_ATTR_ETHERNET */ 375 + nla_total_size(12) /* OVS_KEY_ATTR_ETHERNET */
@@ -600,8 +608,30 @@ static int validate_tp_port(const struct sw_flow_key *flow_key)
600 return -EINVAL; 608 return -EINVAL;
601} 609}
602 610
611static int validate_and_copy_set_tun(const struct nlattr *attr,
612 struct sw_flow_actions **sfa)
613{
614 struct ovs_key_ipv4_tunnel tun_key;
615 int err, start;
616
617 err = ovs_ipv4_tun_from_nlattr(nla_data(attr), &tun_key);
618 if (err)
619 return err;
620
621 start = add_nested_action_start(sfa, OVS_ACTION_ATTR_SET);
622 if (start < 0)
623 return start;
624
625 err = add_action(sfa, OVS_KEY_ATTR_IPV4_TUNNEL, &tun_key, sizeof(tun_key));
626 add_nested_action_end(*sfa, start);
627
628 return err;
629}
630
603static int validate_set(const struct nlattr *a, 631static int validate_set(const struct nlattr *a,
604 const struct sw_flow_key *flow_key) 632 const struct sw_flow_key *flow_key,
633 struct sw_flow_actions **sfa,
634 bool *set_tun)
605{ 635{
606 const struct nlattr *ovs_key = nla_data(a); 636 const struct nlattr *ovs_key = nla_data(a);
607 int key_type = nla_type(ovs_key); 637 int key_type = nla_type(ovs_key);
@@ -611,18 +641,27 @@ static int validate_set(const struct nlattr *a,
611 return -EINVAL; 641 return -EINVAL;
612 642
613 if (key_type > OVS_KEY_ATTR_MAX || 643 if (key_type > OVS_KEY_ATTR_MAX ||
614 nla_len(ovs_key) != ovs_key_lens[key_type]) 644 (ovs_key_lens[key_type] != nla_len(ovs_key) &&
645 ovs_key_lens[key_type] != -1))
615 return -EINVAL; 646 return -EINVAL;
616 647
617 switch (key_type) { 648 switch (key_type) {
618 const struct ovs_key_ipv4 *ipv4_key; 649 const struct ovs_key_ipv4 *ipv4_key;
619 const struct ovs_key_ipv6 *ipv6_key; 650 const struct ovs_key_ipv6 *ipv6_key;
651 int err;
620 652
621 case OVS_KEY_ATTR_PRIORITY: 653 case OVS_KEY_ATTR_PRIORITY:
622 case OVS_KEY_ATTR_SKB_MARK: 654 case OVS_KEY_ATTR_SKB_MARK:
623 case OVS_KEY_ATTR_ETHERNET: 655 case OVS_KEY_ATTR_ETHERNET:
624 break; 656 break;
625 657
658 case OVS_KEY_ATTR_TUNNEL:
659 *set_tun = true;
660 err = validate_and_copy_set_tun(a, sfa);
661 if (err)
662 return err;
663 break;
664
626 case OVS_KEY_ATTR_IPV4: 665 case OVS_KEY_ATTR_IPV4:
627 if (flow_key->eth.type != htons(ETH_P_IP)) 666 if (flow_key->eth.type != htons(ETH_P_IP))
628 return -EINVAL; 667 return -EINVAL;
@@ -771,7 +810,7 @@ static int validate_and_copy_actions(const struct nlattr *attr,
771 break; 810 break;
772 811
773 case OVS_ACTION_ATTR_SET: 812 case OVS_ACTION_ATTR_SET:
774 err = validate_set(a, key); 813 err = validate_set(a, key, sfa, &skip_copy);
775 if (err) 814 if (err)
776 return err; 815 return err;
777 break; 816 break;
@@ -993,6 +1032,33 @@ static int sample_action_to_attr(const struct nlattr *attr, struct sk_buff *skb)
993 return err; 1032 return err;
994} 1033}
995 1034
1035static int set_action_to_attr(const struct nlattr *a, struct sk_buff *skb)
1036{
1037 const struct nlattr *ovs_key = nla_data(a);
1038 int key_type = nla_type(ovs_key);
1039 struct nlattr *start;
1040 int err;
1041
1042 switch (key_type) {
1043 case OVS_KEY_ATTR_IPV4_TUNNEL:
1044 start = nla_nest_start(skb, OVS_ACTION_ATTR_SET);
1045 if (!start)
1046 return -EMSGSIZE;
1047
1048 err = ovs_ipv4_tun_to_nlattr(skb, nla_data(ovs_key));
1049 if (err)
1050 return err;
1051 nla_nest_end(skb, start);
1052 break;
1053 default:
1054 if (nla_put(skb, OVS_ACTION_ATTR_SET, nla_len(a), ovs_key))
1055 return -EMSGSIZE;
1056 break;
1057 }
1058
1059 return 0;
1060}
1061
996static int actions_to_attr(const struct nlattr *attr, int len, struct sk_buff *skb) 1062static int actions_to_attr(const struct nlattr *attr, int len, struct sk_buff *skb)
997{ 1063{
998 const struct nlattr *a; 1064 const struct nlattr *a;
@@ -1002,6 +1068,12 @@ static int actions_to_attr(const struct nlattr *attr, int len, struct sk_buff *s
1002 int type = nla_type(a); 1068 int type = nla_type(a);
1003 1069
1004 switch (type) { 1070 switch (type) {
1071 case OVS_ACTION_ATTR_SET:
1072 err = set_action_to_attr(a, skb);
1073 if (err)
1074 return err;
1075 break;
1076
1005 case OVS_ACTION_ATTR_SAMPLE: 1077 case OVS_ACTION_ATTR_SAMPLE:
1006 err = sample_action_to_attr(a, skb); 1078 err = sample_action_to_attr(a, skb);
1007 if (err) 1079 if (err)