diff options
author | Pravin B Shelar <pshelar@nicira.com> | 2013-10-03 21:16:47 -0400 |
---|---|---|
committer | Jesse Gross <jesse@nicira.com> | 2013-10-03 21:16:47 -0400 |
commit | e64457191a259537bbbfaebeba9a8043786af96f (patch) | |
tree | 579f47d3124b69a94b07878d65d27f71c4f7c9c5 /net/openvswitch/datapath.c | |
parent | f0627cfa24389cab25c67bb7ca902912216a8a2d (diff) |
openvswitch: Restructure datapath.c and flow.c
Over the time datapath.c and flow.c has became pretty large files.
Following patch restructures functionality of component into three
different components:
flow.c: contains flow extract.
flow_netlink.c: netlink flow api.
flow_table.c: flow table api.
This patch restructures code without changing logic.
Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
Signed-off-by: Jesse Gross <jesse@nicira.com>
Diffstat (limited to 'net/openvswitch/datapath.c')
-rw-r--r-- | net/openvswitch/datapath.c | 528 |
1 files changed, 30 insertions, 498 deletions
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 2e1a9c24e380..72e68743c643 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c | |||
@@ -55,10 +55,10 @@ | |||
55 | 55 | ||
56 | #include "datapath.h" | 56 | #include "datapath.h" |
57 | #include "flow.h" | 57 | #include "flow.h" |
58 | #include "flow_netlink.h" | ||
58 | #include "vport-internal_dev.h" | 59 | #include "vport-internal_dev.h" |
59 | #include "vport-netdev.h" | 60 | #include "vport-netdev.h" |
60 | 61 | ||
61 | |||
62 | #define REHASH_FLOW_INTERVAL (10 * 60 * HZ) | 62 | #define REHASH_FLOW_INTERVAL (10 * 60 * HZ) |
63 | 63 | ||
64 | int ovs_net_id __read_mostly; | 64 | int ovs_net_id __read_mostly; |
@@ -235,7 +235,7 @@ void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb) | |||
235 | } | 235 | } |
236 | 236 | ||
237 | /* Look up flow. */ | 237 | /* Look up flow. */ |
238 | flow = ovs_flow_lookup(rcu_dereference(dp->table), &key); | 238 | flow = ovs_flow_tbl_lookup(rcu_dereference(dp->table), &key); |
239 | if (unlikely(!flow)) { | 239 | if (unlikely(!flow)) { |
240 | struct dp_upcall_info upcall; | 240 | struct dp_upcall_info upcall; |
241 | 241 | ||
@@ -433,7 +433,7 @@ static int queue_userspace_packet(struct net *net, int dp_ifindex, | |||
433 | upcall->dp_ifindex = dp_ifindex; | 433 | upcall->dp_ifindex = dp_ifindex; |
434 | 434 | ||
435 | nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_KEY); | 435 | nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_KEY); |
436 | ovs_flow_to_nlattrs(upcall_info->key, upcall_info->key, user_skb); | 436 | ovs_nla_put_flow(upcall_info->key, upcall_info->key, user_skb); |
437 | nla_nest_end(user_skb, nla); | 437 | nla_nest_end(user_skb, nla); |
438 | 438 | ||
439 | if (upcall_info->userdata) | 439 | if (upcall_info->userdata) |
@@ -470,381 +470,6 @@ static int flush_flows(struct datapath *dp) | |||
470 | return 0; | 470 | return 0; |
471 | } | 471 | } |
472 | 472 | ||
473 | static struct nlattr *reserve_sfa_size(struct sw_flow_actions **sfa, int attr_len) | ||
474 | { | ||
475 | |||
476 | struct sw_flow_actions *acts; | ||
477 | int new_acts_size; | ||
478 | int req_size = NLA_ALIGN(attr_len); | ||
479 | int next_offset = offsetof(struct sw_flow_actions, actions) + | ||
480 | (*sfa)->actions_len; | ||
481 | |||
482 | if (req_size <= (ksize(*sfa) - next_offset)) | ||
483 | goto out; | ||
484 | |||
485 | new_acts_size = ksize(*sfa) * 2; | ||
486 | |||
487 | if (new_acts_size > MAX_ACTIONS_BUFSIZE) { | ||
488 | if ((MAX_ACTIONS_BUFSIZE - next_offset) < req_size) | ||
489 | return ERR_PTR(-EMSGSIZE); | ||
490 | new_acts_size = MAX_ACTIONS_BUFSIZE; | ||
491 | } | ||
492 | |||
493 | acts = ovs_flow_actions_alloc(new_acts_size); | ||
494 | if (IS_ERR(acts)) | ||
495 | return (void *)acts; | ||
496 | |||
497 | memcpy(acts->actions, (*sfa)->actions, (*sfa)->actions_len); | ||
498 | acts->actions_len = (*sfa)->actions_len; | ||
499 | kfree(*sfa); | ||
500 | *sfa = acts; | ||
501 | |||
502 | out: | ||
503 | (*sfa)->actions_len += req_size; | ||
504 | return (struct nlattr *) ((unsigned char *)(*sfa) + next_offset); | ||
505 | } | ||
506 | |||
507 | static int add_action(struct sw_flow_actions **sfa, int attrtype, void *data, int len) | ||
508 | { | ||
509 | struct nlattr *a; | ||
510 | |||
511 | a = reserve_sfa_size(sfa, nla_attr_size(len)); | ||
512 | if (IS_ERR(a)) | ||
513 | return PTR_ERR(a); | ||
514 | |||
515 | a->nla_type = attrtype; | ||
516 | a->nla_len = nla_attr_size(len); | ||
517 | |||
518 | if (data) | ||
519 | memcpy(nla_data(a), data, len); | ||
520 | memset((unsigned char *) a + a->nla_len, 0, nla_padlen(len)); | ||
521 | |||
522 | return 0; | ||
523 | } | ||
524 | |||
525 | static inline int add_nested_action_start(struct sw_flow_actions **sfa, int attrtype) | ||
526 | { | ||
527 | int used = (*sfa)->actions_len; | ||
528 | int err; | ||
529 | |||
530 | err = add_action(sfa, attrtype, NULL, 0); | ||
531 | if (err) | ||
532 | return err; | ||
533 | |||
534 | return used; | ||
535 | } | ||
536 | |||
537 | static inline void add_nested_action_end(struct sw_flow_actions *sfa, int st_offset) | ||
538 | { | ||
539 | struct nlattr *a = (struct nlattr *) ((unsigned char *)sfa->actions + st_offset); | ||
540 | |||
541 | a->nla_len = sfa->actions_len - st_offset; | ||
542 | } | ||
543 | |||
544 | static int validate_and_copy_actions(const struct nlattr *attr, | ||
545 | const struct sw_flow_key *key, int depth, | ||
546 | struct sw_flow_actions **sfa); | ||
547 | |||
548 | static int validate_and_copy_sample(const struct nlattr *attr, | ||
549 | const struct sw_flow_key *key, int depth, | ||
550 | struct sw_flow_actions **sfa) | ||
551 | { | ||
552 | const struct nlattr *attrs[OVS_SAMPLE_ATTR_MAX + 1]; | ||
553 | const struct nlattr *probability, *actions; | ||
554 | const struct nlattr *a; | ||
555 | int rem, start, err, st_acts; | ||
556 | |||
557 | memset(attrs, 0, sizeof(attrs)); | ||
558 | nla_for_each_nested(a, attr, rem) { | ||
559 | int type = nla_type(a); | ||
560 | if (!type || type > OVS_SAMPLE_ATTR_MAX || attrs[type]) | ||
561 | return -EINVAL; | ||
562 | attrs[type] = a; | ||
563 | } | ||
564 | if (rem) | ||
565 | return -EINVAL; | ||
566 | |||
567 | probability = attrs[OVS_SAMPLE_ATTR_PROBABILITY]; | ||
568 | if (!probability || nla_len(probability) != sizeof(u32)) | ||
569 | return -EINVAL; | ||
570 | |||
571 | actions = attrs[OVS_SAMPLE_ATTR_ACTIONS]; | ||
572 | if (!actions || (nla_len(actions) && nla_len(actions) < NLA_HDRLEN)) | ||
573 | return -EINVAL; | ||
574 | |||
575 | /* validation done, copy sample action. */ | ||
576 | start = add_nested_action_start(sfa, OVS_ACTION_ATTR_SAMPLE); | ||
577 | if (start < 0) | ||
578 | return start; | ||
579 | err = add_action(sfa, OVS_SAMPLE_ATTR_PROBABILITY, nla_data(probability), sizeof(u32)); | ||
580 | if (err) | ||
581 | return err; | ||
582 | st_acts = add_nested_action_start(sfa, OVS_SAMPLE_ATTR_ACTIONS); | ||
583 | if (st_acts < 0) | ||
584 | return st_acts; | ||
585 | |||
586 | err = validate_and_copy_actions(actions, key, depth + 1, sfa); | ||
587 | if (err) | ||
588 | return err; | ||
589 | |||
590 | add_nested_action_end(*sfa, st_acts); | ||
591 | add_nested_action_end(*sfa, start); | ||
592 | |||
593 | return 0; | ||
594 | } | ||
595 | |||
596 | static int validate_tp_port(const struct sw_flow_key *flow_key) | ||
597 | { | ||
598 | if (flow_key->eth.type == htons(ETH_P_IP)) { | ||
599 | if (flow_key->ipv4.tp.src || flow_key->ipv4.tp.dst) | ||
600 | return 0; | ||
601 | } else if (flow_key->eth.type == htons(ETH_P_IPV6)) { | ||
602 | if (flow_key->ipv6.tp.src || flow_key->ipv6.tp.dst) | ||
603 | return 0; | ||
604 | } | ||
605 | |||
606 | return -EINVAL; | ||
607 | } | ||
608 | |||
609 | static int validate_and_copy_set_tun(const struct nlattr *attr, | ||
610 | struct sw_flow_actions **sfa) | ||
611 | { | ||
612 | struct sw_flow_match match; | ||
613 | struct sw_flow_key key; | ||
614 | int err, start; | ||
615 | |||
616 | ovs_match_init(&match, &key, NULL); | ||
617 | err = ovs_ipv4_tun_from_nlattr(nla_data(attr), &match, false); | ||
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, &match.key->tun_key, | ||
626 | sizeof(match.key->tun_key)); | ||
627 | add_nested_action_end(*sfa, start); | ||
628 | |||
629 | return err; | ||
630 | } | ||
631 | |||
632 | static int validate_set(const struct nlattr *a, | ||
633 | const struct sw_flow_key *flow_key, | ||
634 | struct sw_flow_actions **sfa, | ||
635 | bool *set_tun) | ||
636 | { | ||
637 | const struct nlattr *ovs_key = nla_data(a); | ||
638 | int key_type = nla_type(ovs_key); | ||
639 | |||
640 | /* There can be only one key in a action */ | ||
641 | if (nla_total_size(nla_len(ovs_key)) != nla_len(a)) | ||
642 | return -EINVAL; | ||
643 | |||
644 | if (key_type > OVS_KEY_ATTR_MAX || | ||
645 | (ovs_key_lens[key_type] != nla_len(ovs_key) && | ||
646 | ovs_key_lens[key_type] != -1)) | ||
647 | return -EINVAL; | ||
648 | |||
649 | switch (key_type) { | ||
650 | const struct ovs_key_ipv4 *ipv4_key; | ||
651 | const struct ovs_key_ipv6 *ipv6_key; | ||
652 | int err; | ||
653 | |||
654 | case OVS_KEY_ATTR_PRIORITY: | ||
655 | case OVS_KEY_ATTR_SKB_MARK: | ||
656 | case OVS_KEY_ATTR_ETHERNET: | ||
657 | break; | ||
658 | |||
659 | case OVS_KEY_ATTR_TUNNEL: | ||
660 | *set_tun = true; | ||
661 | err = validate_and_copy_set_tun(a, sfa); | ||
662 | if (err) | ||
663 | return err; | ||
664 | break; | ||
665 | |||
666 | case OVS_KEY_ATTR_IPV4: | ||
667 | if (flow_key->eth.type != htons(ETH_P_IP)) | ||
668 | return -EINVAL; | ||
669 | |||
670 | if (!flow_key->ip.proto) | ||
671 | return -EINVAL; | ||
672 | |||
673 | ipv4_key = nla_data(ovs_key); | ||
674 | if (ipv4_key->ipv4_proto != flow_key->ip.proto) | ||
675 | return -EINVAL; | ||
676 | |||
677 | if (ipv4_key->ipv4_frag != flow_key->ip.frag) | ||
678 | return -EINVAL; | ||
679 | |||
680 | break; | ||
681 | |||
682 | case OVS_KEY_ATTR_IPV6: | ||
683 | if (flow_key->eth.type != htons(ETH_P_IPV6)) | ||
684 | return -EINVAL; | ||
685 | |||
686 | if (!flow_key->ip.proto) | ||
687 | return -EINVAL; | ||
688 | |||
689 | ipv6_key = nla_data(ovs_key); | ||
690 | if (ipv6_key->ipv6_proto != flow_key->ip.proto) | ||
691 | return -EINVAL; | ||
692 | |||
693 | if (ipv6_key->ipv6_frag != flow_key->ip.frag) | ||
694 | return -EINVAL; | ||
695 | |||
696 | if (ntohl(ipv6_key->ipv6_label) & 0xFFF00000) | ||
697 | return -EINVAL; | ||
698 | |||
699 | break; | ||
700 | |||
701 | case OVS_KEY_ATTR_TCP: | ||
702 | if (flow_key->ip.proto != IPPROTO_TCP) | ||
703 | return -EINVAL; | ||
704 | |||
705 | return validate_tp_port(flow_key); | ||
706 | |||
707 | case OVS_KEY_ATTR_UDP: | ||
708 | if (flow_key->ip.proto != IPPROTO_UDP) | ||
709 | return -EINVAL; | ||
710 | |||
711 | return validate_tp_port(flow_key); | ||
712 | |||
713 | case OVS_KEY_ATTR_SCTP: | ||
714 | if (flow_key->ip.proto != IPPROTO_SCTP) | ||
715 | return -EINVAL; | ||
716 | |||
717 | return validate_tp_port(flow_key); | ||
718 | |||
719 | default: | ||
720 | return -EINVAL; | ||
721 | } | ||
722 | |||
723 | return 0; | ||
724 | } | ||
725 | |||
726 | static int validate_userspace(const struct nlattr *attr) | ||
727 | { | ||
728 | static const struct nla_policy userspace_policy[OVS_USERSPACE_ATTR_MAX + 1] = { | ||
729 | [OVS_USERSPACE_ATTR_PID] = {.type = NLA_U32 }, | ||
730 | [OVS_USERSPACE_ATTR_USERDATA] = {.type = NLA_UNSPEC }, | ||
731 | }; | ||
732 | struct nlattr *a[OVS_USERSPACE_ATTR_MAX + 1]; | ||
733 | int error; | ||
734 | |||
735 | error = nla_parse_nested(a, OVS_USERSPACE_ATTR_MAX, | ||
736 | attr, userspace_policy); | ||
737 | if (error) | ||
738 | return error; | ||
739 | |||
740 | if (!a[OVS_USERSPACE_ATTR_PID] || | ||
741 | !nla_get_u32(a[OVS_USERSPACE_ATTR_PID])) | ||
742 | return -EINVAL; | ||
743 | |||
744 | return 0; | ||
745 | } | ||
746 | |||
747 | static int copy_action(const struct nlattr *from, | ||
748 | struct sw_flow_actions **sfa) | ||
749 | { | ||
750 | int totlen = NLA_ALIGN(from->nla_len); | ||
751 | struct nlattr *to; | ||
752 | |||
753 | to = reserve_sfa_size(sfa, from->nla_len); | ||
754 | if (IS_ERR(to)) | ||
755 | return PTR_ERR(to); | ||
756 | |||
757 | memcpy(to, from, totlen); | ||
758 | return 0; | ||
759 | } | ||
760 | |||
761 | static int validate_and_copy_actions(const struct nlattr *attr, | ||
762 | const struct sw_flow_key *key, | ||
763 | int depth, | ||
764 | struct sw_flow_actions **sfa) | ||
765 | { | ||
766 | const struct nlattr *a; | ||
767 | int rem, err; | ||
768 | |||
769 | if (depth >= SAMPLE_ACTION_DEPTH) | ||
770 | return -EOVERFLOW; | ||
771 | |||
772 | nla_for_each_nested(a, attr, rem) { | ||
773 | /* Expected argument lengths, (u32)-1 for variable length. */ | ||
774 | static const u32 action_lens[OVS_ACTION_ATTR_MAX + 1] = { | ||
775 | [OVS_ACTION_ATTR_OUTPUT] = sizeof(u32), | ||
776 | [OVS_ACTION_ATTR_USERSPACE] = (u32)-1, | ||
777 | [OVS_ACTION_ATTR_PUSH_VLAN] = sizeof(struct ovs_action_push_vlan), | ||
778 | [OVS_ACTION_ATTR_POP_VLAN] = 0, | ||
779 | [OVS_ACTION_ATTR_SET] = (u32)-1, | ||
780 | [OVS_ACTION_ATTR_SAMPLE] = (u32)-1 | ||
781 | }; | ||
782 | const struct ovs_action_push_vlan *vlan; | ||
783 | int type = nla_type(a); | ||
784 | bool skip_copy; | ||
785 | |||
786 | if (type > OVS_ACTION_ATTR_MAX || | ||
787 | (action_lens[type] != nla_len(a) && | ||
788 | action_lens[type] != (u32)-1)) | ||
789 | return -EINVAL; | ||
790 | |||
791 | skip_copy = false; | ||
792 | switch (type) { | ||
793 | case OVS_ACTION_ATTR_UNSPEC: | ||
794 | return -EINVAL; | ||
795 | |||
796 | case OVS_ACTION_ATTR_USERSPACE: | ||
797 | err = validate_userspace(a); | ||
798 | if (err) | ||
799 | return err; | ||
800 | break; | ||
801 | |||
802 | case OVS_ACTION_ATTR_OUTPUT: | ||
803 | if (nla_get_u32(a) >= DP_MAX_PORTS) | ||
804 | return -EINVAL; | ||
805 | break; | ||
806 | |||
807 | |||
808 | case OVS_ACTION_ATTR_POP_VLAN: | ||
809 | break; | ||
810 | |||
811 | case OVS_ACTION_ATTR_PUSH_VLAN: | ||
812 | vlan = nla_data(a); | ||
813 | if (vlan->vlan_tpid != htons(ETH_P_8021Q)) | ||
814 | return -EINVAL; | ||
815 | if (!(vlan->vlan_tci & htons(VLAN_TAG_PRESENT))) | ||
816 | return -EINVAL; | ||
817 | break; | ||
818 | |||
819 | case OVS_ACTION_ATTR_SET: | ||
820 | err = validate_set(a, key, sfa, &skip_copy); | ||
821 | if (err) | ||
822 | return err; | ||
823 | break; | ||
824 | |||
825 | case OVS_ACTION_ATTR_SAMPLE: | ||
826 | err = validate_and_copy_sample(a, key, depth, sfa); | ||
827 | if (err) | ||
828 | return err; | ||
829 | skip_copy = true; | ||
830 | break; | ||
831 | |||
832 | default: | ||
833 | return -EINVAL; | ||
834 | } | ||
835 | if (!skip_copy) { | ||
836 | err = copy_action(a, sfa); | ||
837 | if (err) | ||
838 | return err; | ||
839 | } | ||
840 | } | ||
841 | |||
842 | if (rem > 0) | ||
843 | return -EINVAL; | ||
844 | |||
845 | return 0; | ||
846 | } | ||
847 | |||
848 | static void clear_stats(struct sw_flow *flow) | 473 | static void clear_stats(struct sw_flow *flow) |
849 | { | 474 | { |
850 | flow->used = 0; | 475 | flow->used = 0; |
@@ -900,15 +525,16 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info) | |||
900 | if (err) | 525 | if (err) |
901 | goto err_flow_free; | 526 | goto err_flow_free; |
902 | 527 | ||
903 | err = ovs_flow_metadata_from_nlattrs(flow, a[OVS_PACKET_ATTR_KEY]); | 528 | err = ovs_nla_get_flow_metadata(flow, a[OVS_PACKET_ATTR_KEY]); |
904 | if (err) | 529 | if (err) |
905 | goto err_flow_free; | 530 | goto err_flow_free; |
906 | acts = ovs_flow_actions_alloc(nla_len(a[OVS_PACKET_ATTR_ACTIONS])); | 531 | acts = ovs_nla_alloc_flow_actions(nla_len(a[OVS_PACKET_ATTR_ACTIONS])); |
907 | err = PTR_ERR(acts); | 532 | err = PTR_ERR(acts); |
908 | if (IS_ERR(acts)) | 533 | if (IS_ERR(acts)) |
909 | goto err_flow_free; | 534 | goto err_flow_free; |
910 | 535 | ||
911 | err = validate_and_copy_actions(a[OVS_PACKET_ATTR_ACTIONS], &flow->key, 0, &acts); | 536 | err = ovs_nla_copy_actions(a[OVS_PACKET_ATTR_ACTIONS], |
537 | &flow->key, 0, &acts); | ||
912 | rcu_assign_pointer(flow->sf_acts, acts); | 538 | rcu_assign_pointer(flow->sf_acts, acts); |
913 | if (err) | 539 | if (err) |
914 | goto err_flow_free; | 540 | goto err_flow_free; |
@@ -1003,100 +629,6 @@ static struct genl_multicast_group ovs_dp_flow_multicast_group = { | |||
1003 | .name = OVS_FLOW_MCGROUP | 629 | .name = OVS_FLOW_MCGROUP |
1004 | }; | 630 | }; |
1005 | 631 | ||
1006 | static int actions_to_attr(const struct nlattr *attr, int len, struct sk_buff *skb); | ||
1007 | static int sample_action_to_attr(const struct nlattr *attr, struct sk_buff *skb) | ||
1008 | { | ||
1009 | const struct nlattr *a; | ||
1010 | struct nlattr *start; | ||
1011 | int err = 0, rem; | ||
1012 | |||
1013 | start = nla_nest_start(skb, OVS_ACTION_ATTR_SAMPLE); | ||
1014 | if (!start) | ||
1015 | return -EMSGSIZE; | ||
1016 | |||
1017 | nla_for_each_nested(a, attr, rem) { | ||
1018 | int type = nla_type(a); | ||
1019 | struct nlattr *st_sample; | ||
1020 | |||
1021 | switch (type) { | ||
1022 | case OVS_SAMPLE_ATTR_PROBABILITY: | ||
1023 | if (nla_put(skb, OVS_SAMPLE_ATTR_PROBABILITY, sizeof(u32), nla_data(a))) | ||
1024 | return -EMSGSIZE; | ||
1025 | break; | ||
1026 | case OVS_SAMPLE_ATTR_ACTIONS: | ||
1027 | st_sample = nla_nest_start(skb, OVS_SAMPLE_ATTR_ACTIONS); | ||
1028 | if (!st_sample) | ||
1029 | return -EMSGSIZE; | ||
1030 | err = actions_to_attr(nla_data(a), nla_len(a), skb); | ||
1031 | if (err) | ||
1032 | return err; | ||
1033 | nla_nest_end(skb, st_sample); | ||
1034 | break; | ||
1035 | } | ||
1036 | } | ||
1037 | |||
1038 | nla_nest_end(skb, start); | ||
1039 | return err; | ||
1040 | } | ||
1041 | |||
1042 | static int set_action_to_attr(const struct nlattr *a, struct sk_buff *skb) | ||
1043 | { | ||
1044 | const struct nlattr *ovs_key = nla_data(a); | ||
1045 | int key_type = nla_type(ovs_key); | ||
1046 | struct nlattr *start; | ||
1047 | int err; | ||
1048 | |||
1049 | switch (key_type) { | ||
1050 | case OVS_KEY_ATTR_IPV4_TUNNEL: | ||
1051 | start = nla_nest_start(skb, OVS_ACTION_ATTR_SET); | ||
1052 | if (!start) | ||
1053 | return -EMSGSIZE; | ||
1054 | |||
1055 | err = ovs_ipv4_tun_to_nlattr(skb, nla_data(ovs_key), | ||
1056 | nla_data(ovs_key)); | ||
1057 | if (err) | ||
1058 | return err; | ||
1059 | nla_nest_end(skb, start); | ||
1060 | break; | ||
1061 | default: | ||
1062 | if (nla_put(skb, OVS_ACTION_ATTR_SET, nla_len(a), ovs_key)) | ||
1063 | return -EMSGSIZE; | ||
1064 | break; | ||
1065 | } | ||
1066 | |||
1067 | return 0; | ||
1068 | } | ||
1069 | |||
1070 | static int actions_to_attr(const struct nlattr *attr, int len, struct sk_buff *skb) | ||
1071 | { | ||
1072 | const struct nlattr *a; | ||
1073 | int rem, err; | ||
1074 | |||
1075 | nla_for_each_attr(a, attr, len, rem) { | ||
1076 | int type = nla_type(a); | ||
1077 | |||
1078 | switch (type) { | ||
1079 | case OVS_ACTION_ATTR_SET: | ||
1080 | err = set_action_to_attr(a, skb); | ||
1081 | if (err) | ||
1082 | return err; | ||
1083 | break; | ||
1084 | |||
1085 | case OVS_ACTION_ATTR_SAMPLE: | ||
1086 | err = sample_action_to_attr(a, skb); | ||
1087 | if (err) | ||
1088 | return err; | ||
1089 | break; | ||
1090 | default: | ||
1091 | if (nla_put(skb, type, nla_len(a), nla_data(a))) | ||
1092 | return -EMSGSIZE; | ||
1093 | break; | ||
1094 | } | ||
1095 | } | ||
1096 | |||
1097 | return 0; | ||
1098 | } | ||
1099 | |||
1100 | static size_t ovs_flow_cmd_msg_size(const struct sw_flow_actions *acts) | 632 | static size_t ovs_flow_cmd_msg_size(const struct sw_flow_actions *acts) |
1101 | { | 633 | { |
1102 | return NLMSG_ALIGN(sizeof(struct ovs_header)) | 634 | return NLMSG_ALIGN(sizeof(struct ovs_header)) |
@@ -1133,8 +665,7 @@ static int ovs_flow_cmd_fill_info(struct sw_flow *flow, struct datapath *dp, | |||
1133 | if (!nla) | 665 | if (!nla) |
1134 | goto nla_put_failure; | 666 | goto nla_put_failure; |
1135 | 667 | ||
1136 | err = ovs_flow_to_nlattrs(&flow->unmasked_key, | 668 | err = ovs_nla_put_flow(&flow->unmasked_key, &flow->unmasked_key, skb); |
1137 | &flow->unmasked_key, skb); | ||
1138 | if (err) | 669 | if (err) |
1139 | goto error; | 670 | goto error; |
1140 | nla_nest_end(skb, nla); | 671 | nla_nest_end(skb, nla); |
@@ -1143,7 +674,7 @@ static int ovs_flow_cmd_fill_info(struct sw_flow *flow, struct datapath *dp, | |||
1143 | if (!nla) | 674 | if (!nla) |
1144 | goto nla_put_failure; | 675 | goto nla_put_failure; |
1145 | 676 | ||
1146 | err = ovs_flow_to_nlattrs(&flow->key, &flow->mask->key, skb); | 677 | err = ovs_nla_put_flow(&flow->key, &flow->mask->key, skb); |
1147 | if (err) | 678 | if (err) |
1148 | goto error; | 679 | goto error; |
1149 | 680 | ||
@@ -1186,7 +717,8 @@ static int ovs_flow_cmd_fill_info(struct sw_flow *flow, struct datapath *dp, | |||
1186 | sf_acts = rcu_dereference_check(flow->sf_acts, | 717 | sf_acts = rcu_dereference_check(flow->sf_acts, |
1187 | lockdep_ovsl_is_held()); | 718 | lockdep_ovsl_is_held()); |
1188 | 719 | ||
1189 | err = actions_to_attr(sf_acts->actions, sf_acts->actions_len, skb); | 720 | err = ovs_nla_put_actions(sf_acts->actions, |
721 | sf_acts->actions_len, skb); | ||
1190 | if (!err) | 722 | if (!err) |
1191 | nla_nest_end(skb, start); | 723 | nla_nest_end(skb, start); |
1192 | else { | 724 | else { |
@@ -1252,21 +784,21 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info) | |||
1252 | goto error; | 784 | goto error; |
1253 | 785 | ||
1254 | ovs_match_init(&match, &key, &mask); | 786 | ovs_match_init(&match, &key, &mask); |
1255 | error = ovs_match_from_nlattrs(&match, | 787 | error = ovs_nla_get_match(&match, |
1256 | a[OVS_FLOW_ATTR_KEY], a[OVS_FLOW_ATTR_MASK]); | 788 | a[OVS_FLOW_ATTR_KEY], a[OVS_FLOW_ATTR_MASK]); |
1257 | if (error) | 789 | if (error) |
1258 | goto error; | 790 | goto error; |
1259 | 791 | ||
1260 | /* Validate actions. */ | 792 | /* Validate actions. */ |
1261 | if (a[OVS_FLOW_ATTR_ACTIONS]) { | 793 | if (a[OVS_FLOW_ATTR_ACTIONS]) { |
1262 | acts = ovs_flow_actions_alloc(nla_len(a[OVS_FLOW_ATTR_ACTIONS])); | 794 | acts = ovs_nla_alloc_flow_actions(nla_len(a[OVS_FLOW_ATTR_ACTIONS])); |
1263 | error = PTR_ERR(acts); | 795 | error = PTR_ERR(acts); |
1264 | if (IS_ERR(acts)) | 796 | if (IS_ERR(acts)) |
1265 | goto error; | 797 | goto error; |
1266 | 798 | ||
1267 | ovs_flow_key_mask(&masked_key, &key, &mask); | 799 | ovs_flow_mask_key(&masked_key, &key, &mask); |
1268 | error = validate_and_copy_actions(a[OVS_FLOW_ATTR_ACTIONS], | 800 | error = ovs_nla_copy_actions(a[OVS_FLOW_ATTR_ACTIONS], |
1269 | &masked_key, 0, &acts); | 801 | &masked_key, 0, &acts); |
1270 | if (error) { | 802 | if (error) { |
1271 | OVS_NLERR("Flow actions may not be safe on all matching packets.\n"); | 803 | OVS_NLERR("Flow actions may not be safe on all matching packets.\n"); |
1272 | goto err_kfree; | 804 | goto err_kfree; |
@@ -1285,7 +817,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info) | |||
1285 | table = ovsl_dereference(dp->table); | 817 | table = ovsl_dereference(dp->table); |
1286 | 818 | ||
1287 | /* Check if this is a duplicate flow */ | 819 | /* Check if this is a duplicate flow */ |
1288 | flow = ovs_flow_lookup(table, &key); | 820 | flow = ovs_flow_tbl_lookup(table, &key); |
1289 | if (!flow) { | 821 | if (!flow) { |
1290 | struct flow_table *new_table = NULL; | 822 | struct flow_table *new_table = NULL; |
1291 | struct sw_flow_mask *mask_p; | 823 | struct sw_flow_mask *mask_p; |
@@ -1336,7 +868,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info) | |||
1336 | rcu_assign_pointer(flow->sf_acts, acts); | 868 | rcu_assign_pointer(flow->sf_acts, acts); |
1337 | 869 | ||
1338 | /* Put flow in bucket. */ | 870 | /* Put flow in bucket. */ |
1339 | ovs_flow_insert(table, flow); | 871 | ovs_flow_tbl_insert(table, flow); |
1340 | 872 | ||
1341 | reply = ovs_flow_cmd_build_info(flow, dp, info->snd_portid, | 873 | reply = ovs_flow_cmd_build_info(flow, dp, info->snd_portid, |
1342 | info->snd_seq, OVS_FLOW_CMD_NEW); | 874 | info->snd_seq, OVS_FLOW_CMD_NEW); |
@@ -1357,7 +889,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info) | |||
1357 | 889 | ||
1358 | /* The unmasked key has to be the same for flow updates. */ | 890 | /* The unmasked key has to be the same for flow updates. */ |
1359 | error = -EINVAL; | 891 | error = -EINVAL; |
1360 | if (!ovs_flow_cmp_unmasked_key(flow, &key, match.range.end)) { | 892 | if (!ovs_flow_cmp_unmasked_key(flow, &match)) { |
1361 | OVS_NLERR("Flow modification message rejected, unmasked key does not match.\n"); | 893 | OVS_NLERR("Flow modification message rejected, unmasked key does not match.\n"); |
1362 | goto err_unlock_ovs; | 894 | goto err_unlock_ovs; |
1363 | } | 895 | } |
@@ -1365,7 +897,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info) | |||
1365 | /* Update actions. */ | 897 | /* Update actions. */ |
1366 | old_acts = ovsl_dereference(flow->sf_acts); | 898 | old_acts = ovsl_dereference(flow->sf_acts); |
1367 | rcu_assign_pointer(flow->sf_acts, acts); | 899 | rcu_assign_pointer(flow->sf_acts, acts); |
1368 | ovs_flow_deferred_free_acts(old_acts); | 900 | ovs_nla_free_flow_actions(old_acts); |
1369 | 901 | ||
1370 | reply = ovs_flow_cmd_build_info(flow, dp, info->snd_portid, | 902 | reply = ovs_flow_cmd_build_info(flow, dp, info->snd_portid, |
1371 | info->snd_seq, OVS_FLOW_CMD_NEW); | 903 | info->snd_seq, OVS_FLOW_CMD_NEW); |
@@ -1414,7 +946,7 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info) | |||
1414 | } | 946 | } |
1415 | 947 | ||
1416 | ovs_match_init(&match, &key, NULL); | 948 | ovs_match_init(&match, &key, NULL); |
1417 | err = ovs_match_from_nlattrs(&match, a[OVS_FLOW_ATTR_KEY], NULL); | 949 | err = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY], NULL); |
1418 | if (err) | 950 | if (err) |
1419 | return err; | 951 | return err; |
1420 | 952 | ||
@@ -1426,8 +958,8 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info) | |||
1426 | } | 958 | } |
1427 | 959 | ||
1428 | table = ovsl_dereference(dp->table); | 960 | table = ovsl_dereference(dp->table); |
1429 | flow = ovs_flow_lookup_unmasked_key(table, &match); | 961 | flow = ovs_flow_tbl_lookup(table, &key); |
1430 | if (!flow) { | 962 | if (!flow || !ovs_flow_cmp_unmasked_key(flow, &match)) { |
1431 | err = -ENOENT; | 963 | err = -ENOENT; |
1432 | goto unlock; | 964 | goto unlock; |
1433 | } | 965 | } |
@@ -1471,13 +1003,13 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info) | |||
1471 | } | 1003 | } |
1472 | 1004 | ||
1473 | ovs_match_init(&match, &key, NULL); | 1005 | ovs_match_init(&match, &key, NULL); |
1474 | err = ovs_match_from_nlattrs(&match, a[OVS_FLOW_ATTR_KEY], NULL); | 1006 | err = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY], NULL); |
1475 | if (err) | 1007 | if (err) |
1476 | goto unlock; | 1008 | goto unlock; |
1477 | 1009 | ||
1478 | table = ovsl_dereference(dp->table); | 1010 | table = ovsl_dereference(dp->table); |
1479 | flow = ovs_flow_lookup_unmasked_key(table, &match); | 1011 | flow = ovs_flow_tbl_lookup(table, &key); |
1480 | if (!flow) { | 1012 | if (!flow || !ovs_flow_cmp_unmasked_key(flow, &match)) { |
1481 | err = -ENOENT; | 1013 | err = -ENOENT; |
1482 | goto unlock; | 1014 | goto unlock; |
1483 | } | 1015 | } |
@@ -1488,7 +1020,7 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info) | |||
1488 | goto unlock; | 1020 | goto unlock; |
1489 | } | 1021 | } |
1490 | 1022 | ||
1491 | ovs_flow_remove(table, flow); | 1023 | ovs_flow_tbl_remove(table, flow); |
1492 | 1024 | ||
1493 | err = ovs_flow_cmd_fill_info(flow, dp, reply, info->snd_portid, | 1025 | err = ovs_flow_cmd_fill_info(flow, dp, reply, info->snd_portid, |
1494 | info->snd_seq, 0, OVS_FLOW_CMD_DEL); | 1026 | info->snd_seq, 0, OVS_FLOW_CMD_DEL); |
@@ -1524,7 +1056,7 @@ static int ovs_flow_cmd_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
1524 | 1056 | ||
1525 | bucket = cb->args[0]; | 1057 | bucket = cb->args[0]; |
1526 | obj = cb->args[1]; | 1058 | obj = cb->args[1]; |
1527 | flow = ovs_flow_dump_next(table, &bucket, &obj); | 1059 | flow = ovs_flow_tbl_dump_next(table, &bucket, &obj); |
1528 | if (!flow) | 1060 | if (!flow) |
1529 | break; | 1061 | break; |
1530 | 1062 | ||
@@ -1700,7 +1232,7 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info) | |||
1700 | } | 1232 | } |
1701 | 1233 | ||
1702 | dp->ports = kmalloc(DP_VPORT_HASH_BUCKETS * sizeof(struct hlist_head), | 1234 | dp->ports = kmalloc(DP_VPORT_HASH_BUCKETS * sizeof(struct hlist_head), |
1703 | GFP_KERNEL); | 1235 | GFP_KERNEL); |
1704 | if (!dp->ports) { | 1236 | if (!dp->ports) { |
1705 | err = -ENOMEM; | 1237 | err = -ENOMEM; |
1706 | goto err_destroy_percpu; | 1238 | goto err_destroy_percpu; |