diff options
Diffstat (limited to 'net/openvswitch')
-rw-r--r-- | net/openvswitch/actions.c | 9 | ||||
-rw-r--r-- | net/openvswitch/conntrack.c | 24 | ||||
-rw-r--r-- | net/openvswitch/conntrack.h | 16 | ||||
-rw-r--r-- | net/openvswitch/datapath.c | 5 | ||||
-rw-r--r-- | net/openvswitch/datapath.h | 1 | ||||
-rw-r--r-- | net/openvswitch/flow_netlink.c | 26 | ||||
-rw-r--r-- | net/openvswitch/flow_netlink.h | 6 | ||||
-rw-r--r-- | net/openvswitch/vport-geneve.c | 13 | ||||
-rw-r--r-- | net/openvswitch/vport-gre.c | 8 | ||||
-rw-r--r-- | net/openvswitch/vport-internal_dev.c | 46 | ||||
-rw-r--r-- | net/openvswitch/vport-vxlan.c | 20 | ||||
-rw-r--r-- | net/openvswitch/vport.c | 58 | ||||
-rw-r--r-- | net/openvswitch/vport.h | 16 |
13 files changed, 83 insertions, 165 deletions
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c index c6087233d7fc..221fa8b37a47 100644 --- a/net/openvswitch/actions.c +++ b/net/openvswitch/actions.c | |||
@@ -769,7 +769,6 @@ static int output_userspace(struct datapath *dp, struct sk_buff *skb, | |||
769 | struct sw_flow_key *key, const struct nlattr *attr, | 769 | struct sw_flow_key *key, const struct nlattr *attr, |
770 | const struct nlattr *actions, int actions_len) | 770 | const struct nlattr *actions, int actions_len) |
771 | { | 771 | { |
772 | struct ip_tunnel_info info; | ||
773 | struct dp_upcall_info upcall; | 772 | struct dp_upcall_info upcall; |
774 | const struct nlattr *a; | 773 | const struct nlattr *a; |
775 | int rem; | 774 | int rem; |
@@ -797,11 +796,9 @@ static int output_userspace(struct datapath *dp, struct sk_buff *skb, | |||
797 | if (vport) { | 796 | if (vport) { |
798 | int err; | 797 | int err; |
799 | 798 | ||
800 | upcall.egress_tun_info = &info; | 799 | err = dev_fill_metadata_dst(vport->dev, skb); |
801 | err = ovs_vport_get_egress_tun_info(vport, skb, | 800 | if (!err) |
802 | &upcall); | 801 | upcall.egress_tun_info = skb_tunnel_info(skb); |
803 | if (err) | ||
804 | upcall.egress_tun_info = NULL; | ||
805 | } | 802 | } |
806 | 803 | ||
807 | break; | 804 | break; |
diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c index 9ed833e9bb7d..bd165ee2bb16 100644 --- a/net/openvswitch/conntrack.c +++ b/net/openvswitch/conntrack.c | |||
@@ -151,6 +151,8 @@ static void ovs_ct_update_key(const struct sk_buff *skb, | |||
151 | ct = nf_ct_get(skb, &ctinfo); | 151 | ct = nf_ct_get(skb, &ctinfo); |
152 | if (ct) { | 152 | if (ct) { |
153 | state = ovs_ct_get_state(ctinfo); | 153 | state = ovs_ct_get_state(ctinfo); |
154 | if (!nf_ct_is_confirmed(ct)) | ||
155 | state |= OVS_CS_F_NEW; | ||
154 | if (ct->master) | 156 | if (ct->master) |
155 | state |= OVS_CS_F_RELATED; | 157 | state |= OVS_CS_F_RELATED; |
156 | zone = nf_ct_zone(ct); | 158 | zone = nf_ct_zone(ct); |
@@ -222,9 +224,6 @@ static int ovs_ct_set_labels(struct sk_buff *skb, struct sw_flow_key *key, | |||
222 | struct nf_conn *ct; | 224 | struct nf_conn *ct; |
223 | int err; | 225 | int err; |
224 | 226 | ||
225 | if (!IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS)) | ||
226 | return -ENOTSUPP; | ||
227 | |||
228 | /* The connection could be invalid, in which case set_label is no-op.*/ | 227 | /* The connection could be invalid, in which case set_label is no-op.*/ |
229 | ct = nf_ct_get(skb, &ctinfo); | 228 | ct = nf_ct_get(skb, &ctinfo); |
230 | if (!ct) | 229 | if (!ct) |
@@ -377,7 +376,7 @@ static bool skb_nfct_cached(const struct net *net, const struct sk_buff *skb, | |||
377 | return true; | 376 | return true; |
378 | } | 377 | } |
379 | 378 | ||
380 | static int __ovs_ct_lookup(struct net *net, const struct sw_flow_key *key, | 379 | static int __ovs_ct_lookup(struct net *net, struct sw_flow_key *key, |
381 | const struct ovs_conntrack_info *info, | 380 | const struct ovs_conntrack_info *info, |
382 | struct sk_buff *skb) | 381 | struct sk_buff *skb) |
383 | { | 382 | { |
@@ -408,6 +407,8 @@ static int __ovs_ct_lookup(struct net *net, const struct sw_flow_key *key, | |||
408 | } | 407 | } |
409 | } | 408 | } |
410 | 409 | ||
410 | ovs_ct_update_key(skb, key, true); | ||
411 | |||
411 | return 0; | 412 | return 0; |
412 | } | 413 | } |
413 | 414 | ||
@@ -430,8 +431,6 @@ static int ovs_ct_lookup(struct net *net, struct sw_flow_key *key, | |||
430 | err = __ovs_ct_lookup(net, key, info, skb); | 431 | err = __ovs_ct_lookup(net, key, info, skb); |
431 | if (err) | 432 | if (err) |
432 | return err; | 433 | return err; |
433 | |||
434 | ovs_ct_update_key(skb, key, true); | ||
435 | } | 434 | } |
436 | 435 | ||
437 | return 0; | 436 | return 0; |
@@ -460,8 +459,6 @@ static int ovs_ct_commit(struct net *net, struct sw_flow_key *key, | |||
460 | if (nf_conntrack_confirm(skb) != NF_ACCEPT) | 459 | if (nf_conntrack_confirm(skb) != NF_ACCEPT) |
461 | return -EINVAL; | 460 | return -EINVAL; |
462 | 461 | ||
463 | ovs_ct_update_key(skb, key, true); | ||
464 | |||
465 | return 0; | 462 | return 0; |
466 | } | 463 | } |
467 | 464 | ||
@@ -587,6 +584,10 @@ static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info, | |||
587 | case OVS_CT_ATTR_MARK: { | 584 | case OVS_CT_ATTR_MARK: { |
588 | struct md_mark *mark = nla_data(a); | 585 | struct md_mark *mark = nla_data(a); |
589 | 586 | ||
587 | if (!mark->mask) { | ||
588 | OVS_NLERR(log, "ct_mark mask cannot be 0"); | ||
589 | return -EINVAL; | ||
590 | } | ||
590 | info->mark = *mark; | 591 | info->mark = *mark; |
591 | break; | 592 | break; |
592 | } | 593 | } |
@@ -595,6 +596,10 @@ static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info, | |||
595 | case OVS_CT_ATTR_LABELS: { | 596 | case OVS_CT_ATTR_LABELS: { |
596 | struct md_labels *labels = nla_data(a); | 597 | struct md_labels *labels = nla_data(a); |
597 | 598 | ||
599 | if (!labels_nonzero(&labels->mask)) { | ||
600 | OVS_NLERR(log, "ct_labels mask cannot be 0"); | ||
601 | return -EINVAL; | ||
602 | } | ||
598 | info->labels = *labels; | 603 | info->labels = *labels; |
599 | break; | 604 | break; |
600 | } | 605 | } |
@@ -705,11 +710,12 @@ int ovs_ct_action_to_attr(const struct ovs_conntrack_info *ct_info, | |||
705 | if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) && | 710 | if (IS_ENABLED(CONFIG_NF_CONNTRACK_ZONES) && |
706 | nla_put_u16(skb, OVS_CT_ATTR_ZONE, ct_info->zone.id)) | 711 | nla_put_u16(skb, OVS_CT_ATTR_ZONE, ct_info->zone.id)) |
707 | return -EMSGSIZE; | 712 | return -EMSGSIZE; |
708 | if (IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) && | 713 | if (IS_ENABLED(CONFIG_NF_CONNTRACK_MARK) && ct_info->mark.mask && |
709 | nla_put(skb, OVS_CT_ATTR_MARK, sizeof(ct_info->mark), | 714 | nla_put(skb, OVS_CT_ATTR_MARK, sizeof(ct_info->mark), |
710 | &ct_info->mark)) | 715 | &ct_info->mark)) |
711 | return -EMSGSIZE; | 716 | return -EMSGSIZE; |
712 | if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) && | 717 | if (IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS) && |
718 | labels_nonzero(&ct_info->labels.mask) && | ||
713 | nla_put(skb, OVS_CT_ATTR_LABELS, sizeof(ct_info->labels), | 719 | nla_put(skb, OVS_CT_ATTR_LABELS, sizeof(ct_info->labels), |
714 | &ct_info->labels)) | 720 | &ct_info->labels)) |
715 | return -EMSGSIZE; | 721 | return -EMSGSIZE; |
diff --git a/net/openvswitch/conntrack.h b/net/openvswitch/conntrack.h index da8714942c95..82e0dfc66028 100644 --- a/net/openvswitch/conntrack.h +++ b/net/openvswitch/conntrack.h | |||
@@ -35,12 +35,9 @@ void ovs_ct_fill_key(const struct sk_buff *skb, struct sw_flow_key *key); | |||
35 | int ovs_ct_put_key(const struct sw_flow_key *key, struct sk_buff *skb); | 35 | int ovs_ct_put_key(const struct sw_flow_key *key, struct sk_buff *skb); |
36 | void ovs_ct_free_action(const struct nlattr *a); | 36 | void ovs_ct_free_action(const struct nlattr *a); |
37 | 37 | ||
38 | static inline bool ovs_ct_state_supported(u32 state) | 38 | #define CT_SUPPORTED_MASK (OVS_CS_F_NEW | OVS_CS_F_ESTABLISHED | \ |
39 | { | 39 | OVS_CS_F_RELATED | OVS_CS_F_REPLY_DIR | \ |
40 | return !(state & ~(OVS_CS_F_NEW | OVS_CS_F_ESTABLISHED | | 40 | OVS_CS_F_INVALID | OVS_CS_F_TRACKED) |
41 | OVS_CS_F_RELATED | OVS_CS_F_REPLY_DIR | | ||
42 | OVS_CS_F_INVALID | OVS_CS_F_TRACKED)); | ||
43 | } | ||
44 | #else | 41 | #else |
45 | #include <linux/errno.h> | 42 | #include <linux/errno.h> |
46 | 43 | ||
@@ -53,11 +50,6 @@ static inline bool ovs_ct_verify(struct net *net, int attr) | |||
53 | return false; | 50 | return false; |
54 | } | 51 | } |
55 | 52 | ||
56 | static inline bool ovs_ct_state_supported(u32 state) | ||
57 | { | ||
58 | return false; | ||
59 | } | ||
60 | |||
61 | static inline int ovs_ct_copy_action(struct net *net, const struct nlattr *nla, | 53 | static inline int ovs_ct_copy_action(struct net *net, const struct nlattr *nla, |
62 | const struct sw_flow_key *key, | 54 | const struct sw_flow_key *key, |
63 | struct sw_flow_actions **acts, bool log) | 55 | struct sw_flow_actions **acts, bool log) |
@@ -94,5 +86,7 @@ static inline int ovs_ct_put_key(const struct sw_flow_key *key, | |||
94 | } | 86 | } |
95 | 87 | ||
96 | static inline void ovs_ct_free_action(const struct nlattr *a) { } | 88 | static inline void ovs_ct_free_action(const struct nlattr *a) { } |
89 | |||
90 | #define CT_SUPPORTED_MASK 0 | ||
97 | #endif /* CONFIG_NF_CONNTRACK */ | 91 | #endif /* CONFIG_NF_CONNTRACK */ |
98 | #endif /* ovs_conntrack.h */ | 92 | #endif /* ovs_conntrack.h */ |
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index a75828091e21..5633172b791a 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c | |||
@@ -489,9 +489,8 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, | |||
489 | 489 | ||
490 | if (upcall_info->egress_tun_info) { | 490 | if (upcall_info->egress_tun_info) { |
491 | nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_EGRESS_TUN_KEY); | 491 | nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_EGRESS_TUN_KEY); |
492 | err = ovs_nla_put_egress_tunnel_key(user_skb, | 492 | err = ovs_nla_put_tunnel_info(user_skb, |
493 | upcall_info->egress_tun_info, | 493 | upcall_info->egress_tun_info); |
494 | upcall_info->egress_tun_opts); | ||
495 | BUG_ON(err); | 494 | BUG_ON(err); |
496 | nla_nest_end(user_skb, nla); | 495 | nla_nest_end(user_skb, nla); |
497 | } | 496 | } |
diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h index f88038a99f44..67bdecd9fdc1 100644 --- a/net/openvswitch/datapath.h +++ b/net/openvswitch/datapath.h | |||
@@ -117,7 +117,6 @@ struct ovs_skb_cb { | |||
117 | */ | 117 | */ |
118 | struct dp_upcall_info { | 118 | struct dp_upcall_info { |
119 | struct ip_tunnel_info *egress_tun_info; | 119 | struct ip_tunnel_info *egress_tun_info; |
120 | const void *egress_tun_opts; | ||
121 | const struct nlattr *userdata; | 120 | const struct nlattr *userdata; |
122 | const struct nlattr *actions; | 121 | const struct nlattr *actions; |
123 | int actions_len; | 122 | int actions_len; |
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c index 80e1f09397c0..907d6fd28ede 100644 --- a/net/openvswitch/flow_netlink.c +++ b/net/openvswitch/flow_netlink.c | |||
@@ -764,7 +764,7 @@ static int __ip_tun_to_nlattr(struct sk_buff *skb, | |||
764 | if ((output->tun_flags & TUNNEL_OAM) && | 764 | if ((output->tun_flags & TUNNEL_OAM) && |
765 | nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_OAM)) | 765 | nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_OAM)) |
766 | return -EMSGSIZE; | 766 | return -EMSGSIZE; |
767 | if (tun_opts) { | 767 | if (swkey_tun_opts_len) { |
768 | if (output->tun_flags & TUNNEL_GENEVE_OPT && | 768 | if (output->tun_flags & TUNNEL_GENEVE_OPT && |
769 | nla_put(skb, OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS, | 769 | nla_put(skb, OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS, |
770 | swkey_tun_opts_len, tun_opts)) | 770 | swkey_tun_opts_len, tun_opts)) |
@@ -798,14 +798,13 @@ static int ip_tun_to_nlattr(struct sk_buff *skb, | |||
798 | return 0; | 798 | return 0; |
799 | } | 799 | } |
800 | 800 | ||
801 | int ovs_nla_put_egress_tunnel_key(struct sk_buff *skb, | 801 | int ovs_nla_put_tunnel_info(struct sk_buff *skb, |
802 | const struct ip_tunnel_info *egress_tun_info, | 802 | struct ip_tunnel_info *tun_info) |
803 | const void *egress_tun_opts) | ||
804 | { | 803 | { |
805 | return __ip_tun_to_nlattr(skb, &egress_tun_info->key, | 804 | return __ip_tun_to_nlattr(skb, &tun_info->key, |
806 | egress_tun_opts, | 805 | ip_tunnel_info_opts(tun_info), |
807 | egress_tun_info->options_len, | 806 | tun_info->options_len, |
808 | ip_tunnel_info_af(egress_tun_info)); | 807 | ip_tunnel_info_af(tun_info)); |
809 | } | 808 | } |
810 | 809 | ||
811 | static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match, | 810 | static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match, |
@@ -866,7 +865,7 @@ static int metadata_from_nlattrs(struct net *net, struct sw_flow_match *match, | |||
866 | ovs_ct_verify(net, OVS_KEY_ATTR_CT_STATE)) { | 865 | ovs_ct_verify(net, OVS_KEY_ATTR_CT_STATE)) { |
867 | u32 ct_state = nla_get_u32(a[OVS_KEY_ATTR_CT_STATE]); | 866 | u32 ct_state = nla_get_u32(a[OVS_KEY_ATTR_CT_STATE]); |
868 | 867 | ||
869 | if (!is_mask && !ovs_ct_state_supported(ct_state)) { | 868 | if (ct_state & ~CT_SUPPORTED_MASK) { |
870 | OVS_NLERR(log, "ct_state flags %08x unsupported", | 869 | OVS_NLERR(log, "ct_state flags %08x unsupported", |
871 | ct_state); | 870 | ct_state); |
872 | return -EINVAL; | 871 | return -EINVAL; |
@@ -1149,6 +1148,9 @@ static void nlattr_set(struct nlattr *attr, u8 val, | |||
1149 | } else { | 1148 | } else { |
1150 | memset(nla_data(nla), val, nla_len(nla)); | 1149 | memset(nla_data(nla), val, nla_len(nla)); |
1151 | } | 1150 | } |
1151 | |||
1152 | if (nla_type(nla) == OVS_KEY_ATTR_CT_STATE) | ||
1153 | *(u32 *)nla_data(nla) &= CT_SUPPORTED_MASK; | ||
1152 | } | 1154 | } |
1153 | } | 1155 | } |
1154 | 1156 | ||
@@ -2432,11 +2434,7 @@ static int set_action_to_attr(const struct nlattr *a, struct sk_buff *skb) | |||
2432 | if (!start) | 2434 | if (!start) |
2433 | return -EMSGSIZE; | 2435 | return -EMSGSIZE; |
2434 | 2436 | ||
2435 | err = ip_tun_to_nlattr(skb, &tun_info->key, | 2437 | err = ovs_nla_put_tunnel_info(skb, tun_info); |
2436 | tun_info->options_len ? | ||
2437 | ip_tunnel_info_opts(tun_info) : NULL, | ||
2438 | tun_info->options_len, | ||
2439 | ip_tunnel_info_af(tun_info)); | ||
2440 | if (err) | 2438 | if (err) |
2441 | return err; | 2439 | return err; |
2442 | nla_nest_end(skb, start); | 2440 | nla_nest_end(skb, start); |
diff --git a/net/openvswitch/flow_netlink.h b/net/openvswitch/flow_netlink.h index 6ca3f0baf449..47dd142eca1c 100644 --- a/net/openvswitch/flow_netlink.h +++ b/net/openvswitch/flow_netlink.h | |||
@@ -55,9 +55,9 @@ int ovs_nla_put_mask(const struct sw_flow *flow, struct sk_buff *skb); | |||
55 | int ovs_nla_get_match(struct net *, struct sw_flow_match *, | 55 | int ovs_nla_get_match(struct net *, struct sw_flow_match *, |
56 | const struct nlattr *key, const struct nlattr *mask, | 56 | const struct nlattr *key, const struct nlattr *mask, |
57 | bool log); | 57 | bool log); |
58 | int ovs_nla_put_egress_tunnel_key(struct sk_buff *, | 58 | |
59 | const struct ip_tunnel_info *, | 59 | int ovs_nla_put_tunnel_info(struct sk_buff *skb, |
60 | const void *egress_tun_opts); | 60 | struct ip_tunnel_info *tun_info); |
61 | 61 | ||
62 | bool ovs_nla_get_ufid(struct sw_flow_id *, const struct nlattr *, bool log); | 62 | bool ovs_nla_get_ufid(struct sw_flow_id *, const struct nlattr *, bool log); |
63 | int ovs_nla_get_identifier(struct sw_flow_id *sfid, const struct nlattr *ufid, | 63 | int ovs_nla_get_identifier(struct sw_flow_id *sfid, const struct nlattr *ufid, |
diff --git a/net/openvswitch/vport-geneve.c b/net/openvswitch/vport-geneve.c index 7a568ca8da54..efb736bb6855 100644 --- a/net/openvswitch/vport-geneve.c +++ b/net/openvswitch/vport-geneve.c | |||
@@ -52,18 +52,6 @@ static int geneve_get_options(const struct vport *vport, | |||
52 | return 0; | 52 | return 0; |
53 | } | 53 | } |
54 | 54 | ||
55 | static int geneve_get_egress_tun_info(struct vport *vport, struct sk_buff *skb, | ||
56 | struct dp_upcall_info *upcall) | ||
57 | { | ||
58 | struct geneve_port *geneve_port = geneve_vport(vport); | ||
59 | struct net *net = ovs_dp_get_net(vport->dp); | ||
60 | __be16 dport = htons(geneve_port->port_no); | ||
61 | __be16 sport = udp_flow_src_port(net, skb, 1, USHRT_MAX, true); | ||
62 | |||
63 | return ovs_tunnel_get_egress_info(upcall, ovs_dp_get_net(vport->dp), | ||
64 | skb, IPPROTO_UDP, sport, dport); | ||
65 | } | ||
66 | |||
67 | static struct vport *geneve_tnl_create(const struct vport_parms *parms) | 55 | static struct vport *geneve_tnl_create(const struct vport_parms *parms) |
68 | { | 56 | { |
69 | struct net *net = ovs_dp_get_net(parms->dp); | 57 | struct net *net = ovs_dp_get_net(parms->dp); |
@@ -130,7 +118,6 @@ static struct vport_ops ovs_geneve_vport_ops = { | |||
130 | .get_options = geneve_get_options, | 118 | .get_options = geneve_get_options, |
131 | .send = dev_queue_xmit, | 119 | .send = dev_queue_xmit, |
132 | .owner = THIS_MODULE, | 120 | .owner = THIS_MODULE, |
133 | .get_egress_tun_info = geneve_get_egress_tun_info, | ||
134 | }; | 121 | }; |
135 | 122 | ||
136 | static int __init ovs_geneve_tnl_init(void) | 123 | static int __init ovs_geneve_tnl_init(void) |
diff --git a/net/openvswitch/vport-gre.c b/net/openvswitch/vport-gre.c index cdb758ab01cf..c3257d78d3d2 100644 --- a/net/openvswitch/vport-gre.c +++ b/net/openvswitch/vport-gre.c | |||
@@ -84,18 +84,10 @@ static struct vport *gre_create(const struct vport_parms *parms) | |||
84 | return ovs_netdev_link(vport, parms->name); | 84 | return ovs_netdev_link(vport, parms->name); |
85 | } | 85 | } |
86 | 86 | ||
87 | static int gre_get_egress_tun_info(struct vport *vport, struct sk_buff *skb, | ||
88 | struct dp_upcall_info *upcall) | ||
89 | { | ||
90 | return ovs_tunnel_get_egress_info(upcall, ovs_dp_get_net(vport->dp), | ||
91 | skb, IPPROTO_GRE, 0, 0); | ||
92 | } | ||
93 | |||
94 | static struct vport_ops ovs_gre_vport_ops = { | 87 | static struct vport_ops ovs_gre_vport_ops = { |
95 | .type = OVS_VPORT_TYPE_GRE, | 88 | .type = OVS_VPORT_TYPE_GRE, |
96 | .create = gre_create, | 89 | .create = gre_create, |
97 | .send = dev_queue_xmit, | 90 | .send = dev_queue_xmit, |
98 | .get_egress_tun_info = gre_get_egress_tun_info, | ||
99 | .destroy = ovs_netdev_tunnel_destroy, | 91 | .destroy = ovs_netdev_tunnel_destroy, |
100 | .owner = THIS_MODULE, | 92 | .owner = THIS_MODULE, |
101 | }; | 93 | }; |
diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c index 7f0a8bd08857..ec76398a792f 100644 --- a/net/openvswitch/vport-internal_dev.c +++ b/net/openvswitch/vport-internal_dev.c | |||
@@ -106,12 +106,45 @@ static void internal_dev_destructor(struct net_device *dev) | |||
106 | free_netdev(dev); | 106 | free_netdev(dev); |
107 | } | 107 | } |
108 | 108 | ||
109 | static struct rtnl_link_stats64 * | ||
110 | internal_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats) | ||
111 | { | ||
112 | int i; | ||
113 | |||
114 | memset(stats, 0, sizeof(*stats)); | ||
115 | stats->rx_errors = dev->stats.rx_errors; | ||
116 | stats->tx_errors = dev->stats.tx_errors; | ||
117 | stats->tx_dropped = dev->stats.tx_dropped; | ||
118 | stats->rx_dropped = dev->stats.rx_dropped; | ||
119 | |||
120 | for_each_possible_cpu(i) { | ||
121 | const struct pcpu_sw_netstats *percpu_stats; | ||
122 | struct pcpu_sw_netstats local_stats; | ||
123 | unsigned int start; | ||
124 | |||
125 | percpu_stats = per_cpu_ptr(dev->tstats, i); | ||
126 | |||
127 | do { | ||
128 | start = u64_stats_fetch_begin_irq(&percpu_stats->syncp); | ||
129 | local_stats = *percpu_stats; | ||
130 | } while (u64_stats_fetch_retry_irq(&percpu_stats->syncp, start)); | ||
131 | |||
132 | stats->rx_bytes += local_stats.rx_bytes; | ||
133 | stats->rx_packets += local_stats.rx_packets; | ||
134 | stats->tx_bytes += local_stats.tx_bytes; | ||
135 | stats->tx_packets += local_stats.tx_packets; | ||
136 | } | ||
137 | |||
138 | return stats; | ||
139 | } | ||
140 | |||
109 | static const struct net_device_ops internal_dev_netdev_ops = { | 141 | static const struct net_device_ops internal_dev_netdev_ops = { |
110 | .ndo_open = internal_dev_open, | 142 | .ndo_open = internal_dev_open, |
111 | .ndo_stop = internal_dev_stop, | 143 | .ndo_stop = internal_dev_stop, |
112 | .ndo_start_xmit = internal_dev_xmit, | 144 | .ndo_start_xmit = internal_dev_xmit, |
113 | .ndo_set_mac_address = eth_mac_addr, | 145 | .ndo_set_mac_address = eth_mac_addr, |
114 | .ndo_change_mtu = internal_dev_change_mtu, | 146 | .ndo_change_mtu = internal_dev_change_mtu, |
147 | .ndo_get_stats64 = internal_get_stats, | ||
115 | }; | 148 | }; |
116 | 149 | ||
117 | static struct rtnl_link_ops internal_dev_link_ops __read_mostly = { | 150 | static struct rtnl_link_ops internal_dev_link_ops __read_mostly = { |
@@ -161,6 +194,11 @@ static struct vport *internal_dev_create(const struct vport_parms *parms) | |||
161 | err = -ENOMEM; | 194 | err = -ENOMEM; |
162 | goto error_free_vport; | 195 | goto error_free_vport; |
163 | } | 196 | } |
197 | vport->dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); | ||
198 | if (!vport->dev->tstats) { | ||
199 | err = -ENOMEM; | ||
200 | goto error_free_netdev; | ||
201 | } | ||
164 | 202 | ||
165 | dev_net_set(vport->dev, ovs_dp_get_net(vport->dp)); | 203 | dev_net_set(vport->dev, ovs_dp_get_net(vport->dp)); |
166 | internal_dev = internal_dev_priv(vport->dev); | 204 | internal_dev = internal_dev_priv(vport->dev); |
@@ -173,7 +211,7 @@ static struct vport *internal_dev_create(const struct vport_parms *parms) | |||
173 | rtnl_lock(); | 211 | rtnl_lock(); |
174 | err = register_netdevice(vport->dev); | 212 | err = register_netdevice(vport->dev); |
175 | if (err) | 213 | if (err) |
176 | goto error_free_netdev; | 214 | goto error_unlock; |
177 | 215 | ||
178 | dev_set_promiscuity(vport->dev, 1); | 216 | dev_set_promiscuity(vport->dev, 1); |
179 | rtnl_unlock(); | 217 | rtnl_unlock(); |
@@ -181,8 +219,10 @@ static struct vport *internal_dev_create(const struct vport_parms *parms) | |||
181 | 219 | ||
182 | return vport; | 220 | return vport; |
183 | 221 | ||
184 | error_free_netdev: | 222 | error_unlock: |
185 | rtnl_unlock(); | 223 | rtnl_unlock(); |
224 | free_percpu(vport->dev->tstats); | ||
225 | error_free_netdev: | ||
186 | free_netdev(vport->dev); | 226 | free_netdev(vport->dev); |
187 | error_free_vport: | 227 | error_free_vport: |
188 | ovs_vport_free(vport); | 228 | ovs_vport_free(vport); |
@@ -198,7 +238,7 @@ static void internal_dev_destroy(struct vport *vport) | |||
198 | 238 | ||
199 | /* unregister_netdevice() waits for an RCU grace period. */ | 239 | /* unregister_netdevice() waits for an RCU grace period. */ |
200 | unregister_netdevice(vport->dev); | 240 | unregister_netdevice(vport->dev); |
201 | 241 | free_percpu(vport->dev->tstats); | |
202 | rtnl_unlock(); | 242 | rtnl_unlock(); |
203 | } | 243 | } |
204 | 244 | ||
diff --git a/net/openvswitch/vport-vxlan.c b/net/openvswitch/vport-vxlan.c index 6f700710d413..1605691d9414 100644 --- a/net/openvswitch/vport-vxlan.c +++ b/net/openvswitch/vport-vxlan.c | |||
@@ -146,32 +146,12 @@ static struct vport *vxlan_create(const struct vport_parms *parms) | |||
146 | return ovs_netdev_link(vport, parms->name); | 146 | return ovs_netdev_link(vport, parms->name); |
147 | } | 147 | } |
148 | 148 | ||
149 | static int vxlan_get_egress_tun_info(struct vport *vport, struct sk_buff *skb, | ||
150 | struct dp_upcall_info *upcall) | ||
151 | { | ||
152 | struct vxlan_dev *vxlan = netdev_priv(vport->dev); | ||
153 | struct net *net = ovs_dp_get_net(vport->dp); | ||
154 | unsigned short family = ip_tunnel_info_af(upcall->egress_tun_info); | ||
155 | __be16 dst_port = vxlan_dev_dst_port(vxlan, family); | ||
156 | __be16 src_port; | ||
157 | int port_min; | ||
158 | int port_max; | ||
159 | |||
160 | inet_get_local_port_range(net, &port_min, &port_max); | ||
161 | src_port = udp_flow_src_port(net, skb, 0, 0, true); | ||
162 | |||
163 | return ovs_tunnel_get_egress_info(upcall, net, | ||
164 | skb, IPPROTO_UDP, | ||
165 | src_port, dst_port); | ||
166 | } | ||
167 | |||
168 | static struct vport_ops ovs_vxlan_netdev_vport_ops = { | 149 | static struct vport_ops ovs_vxlan_netdev_vport_ops = { |
169 | .type = OVS_VPORT_TYPE_VXLAN, | 150 | .type = OVS_VPORT_TYPE_VXLAN, |
170 | .create = vxlan_create, | 151 | .create = vxlan_create, |
171 | .destroy = ovs_netdev_tunnel_destroy, | 152 | .destroy = ovs_netdev_tunnel_destroy, |
172 | .get_options = vxlan_get_options, | 153 | .get_options = vxlan_get_options, |
173 | .send = dev_queue_xmit, | 154 | .send = dev_queue_xmit, |
174 | .get_egress_tun_info = vxlan_get_egress_tun_info, | ||
175 | }; | 155 | }; |
176 | 156 | ||
177 | static int __init ovs_vxlan_tnl_init(void) | 157 | static int __init ovs_vxlan_tnl_init(void) |
diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c index ef19d0b77d13..0ac0fd004d7e 100644 --- a/net/openvswitch/vport.c +++ b/net/openvswitch/vport.c | |||
@@ -480,64 +480,6 @@ void ovs_vport_deferred_free(struct vport *vport) | |||
480 | } | 480 | } |
481 | EXPORT_SYMBOL_GPL(ovs_vport_deferred_free); | 481 | EXPORT_SYMBOL_GPL(ovs_vport_deferred_free); |
482 | 482 | ||
483 | int ovs_tunnel_get_egress_info(struct dp_upcall_info *upcall, | ||
484 | struct net *net, | ||
485 | struct sk_buff *skb, | ||
486 | u8 ipproto, | ||
487 | __be16 tp_src, | ||
488 | __be16 tp_dst) | ||
489 | { | ||
490 | struct ip_tunnel_info *egress_tun_info = upcall->egress_tun_info; | ||
491 | const struct ip_tunnel_info *tun_info = skb_tunnel_info(skb); | ||
492 | const struct ip_tunnel_key *tun_key; | ||
493 | u32 skb_mark = skb->mark; | ||
494 | struct rtable *rt; | ||
495 | struct flowi4 fl; | ||
496 | |||
497 | if (unlikely(!tun_info)) | ||
498 | return -EINVAL; | ||
499 | if (ip_tunnel_info_af(tun_info) != AF_INET) | ||
500 | return -EINVAL; | ||
501 | |||
502 | tun_key = &tun_info->key; | ||
503 | |||
504 | /* Route lookup to get srouce IP address. | ||
505 | * The process may need to be changed if the corresponding process | ||
506 | * in vports ops changed. | ||
507 | */ | ||
508 | rt = ovs_tunnel_route_lookup(net, tun_key, skb_mark, &fl, ipproto); | ||
509 | if (IS_ERR(rt)) | ||
510 | return PTR_ERR(rt); | ||
511 | |||
512 | ip_rt_put(rt); | ||
513 | |||
514 | /* Generate egress_tun_info based on tun_info, | ||
515 | * saddr, tp_src and tp_dst | ||
516 | */ | ||
517 | ip_tunnel_key_init(&egress_tun_info->key, | ||
518 | fl.saddr, tun_key->u.ipv4.dst, | ||
519 | tun_key->tos, | ||
520 | tun_key->ttl, | ||
521 | tp_src, tp_dst, | ||
522 | tun_key->tun_id, | ||
523 | tun_key->tun_flags); | ||
524 | egress_tun_info->options_len = tun_info->options_len; | ||
525 | egress_tun_info->mode = tun_info->mode; | ||
526 | upcall->egress_tun_opts = ip_tunnel_info_opts(egress_tun_info); | ||
527 | return 0; | ||
528 | } | ||
529 | EXPORT_SYMBOL_GPL(ovs_tunnel_get_egress_info); | ||
530 | |||
531 | int ovs_vport_get_egress_tun_info(struct vport *vport, struct sk_buff *skb, | ||
532 | struct dp_upcall_info *upcall) | ||
533 | { | ||
534 | /* get_egress_tun_info() is only implemented on tunnel ports. */ | ||
535 | if (unlikely(!vport->ops->get_egress_tun_info)) | ||
536 | return -EINVAL; | ||
537 | |||
538 | return vport->ops->get_egress_tun_info(vport, skb, upcall); | ||
539 | } | ||
540 | |||
541 | static unsigned int packet_length(const struct sk_buff *skb) | 483 | static unsigned int packet_length(const struct sk_buff *skb) |
542 | { | 484 | { |
543 | unsigned int length = skb->len - ETH_HLEN; | 485 | unsigned int length = skb->len - ETH_HLEN; |
diff --git a/net/openvswitch/vport.h b/net/openvswitch/vport.h index 885607f28d56..bdfd82a7c064 100644 --- a/net/openvswitch/vport.h +++ b/net/openvswitch/vport.h | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <linux/skbuff.h> | 27 | #include <linux/skbuff.h> |
28 | #include <linux/spinlock.h> | 28 | #include <linux/spinlock.h> |
29 | #include <linux/u64_stats_sync.h> | 29 | #include <linux/u64_stats_sync.h> |
30 | #include <net/route.h> | ||
31 | 30 | ||
32 | #include "datapath.h" | 31 | #include "datapath.h" |
33 | 32 | ||
@@ -53,16 +52,6 @@ int ovs_vport_set_upcall_portids(struct vport *, const struct nlattr *pids); | |||
53 | int ovs_vport_get_upcall_portids(const struct vport *, struct sk_buff *); | 52 | int ovs_vport_get_upcall_portids(const struct vport *, struct sk_buff *); |
54 | u32 ovs_vport_find_upcall_portid(const struct vport *, struct sk_buff *); | 53 | u32 ovs_vport_find_upcall_portid(const struct vport *, struct sk_buff *); |
55 | 54 | ||
56 | int ovs_tunnel_get_egress_info(struct dp_upcall_info *upcall, | ||
57 | struct net *net, | ||
58 | struct sk_buff *, | ||
59 | u8 ipproto, | ||
60 | __be16 tp_src, | ||
61 | __be16 tp_dst); | ||
62 | |||
63 | int ovs_vport_get_egress_tun_info(struct vport *vport, struct sk_buff *skb, | ||
64 | struct dp_upcall_info *upcall); | ||
65 | |||
66 | /** | 55 | /** |
67 | * struct vport_portids - array of netlink portids of a vport. | 56 | * struct vport_portids - array of netlink portids of a vport. |
68 | * must be protected by rcu. | 57 | * must be protected by rcu. |
@@ -140,8 +129,6 @@ struct vport_parms { | |||
140 | * have any configuration. | 129 | * have any configuration. |
141 | * @send: Send a packet on the device. | 130 | * @send: Send a packet on the device. |
142 | * zero for dropped packets or negative for error. | 131 | * zero for dropped packets or negative for error. |
143 | * @get_egress_tun_info: Get the egress tunnel 5-tuple and other info for | ||
144 | * a packet. | ||
145 | */ | 132 | */ |
146 | struct vport_ops { | 133 | struct vport_ops { |
147 | enum ovs_vport_type type; | 134 | enum ovs_vport_type type; |
@@ -154,9 +141,6 @@ struct vport_ops { | |||
154 | int (*get_options)(const struct vport *, struct sk_buff *); | 141 | int (*get_options)(const struct vport *, struct sk_buff *); |
155 | 142 | ||
156 | netdev_tx_t (*send) (struct sk_buff *skb); | 143 | netdev_tx_t (*send) (struct sk_buff *skb); |
157 | int (*get_egress_tun_info)(struct vport *, struct sk_buff *, | ||
158 | struct dp_upcall_info *upcall); | ||
159 | |||
160 | struct module *owner; | 144 | struct module *owner; |
161 | struct list_head list; | 145 | struct list_head list; |
162 | }; | 146 | }; |