diff options
| author | Thomas Graf <tgraf@suug.ch> | 2013-11-30 07:21:32 -0500 |
|---|---|---|
| committer | Jesse Gross <jesse@nicira.com> | 2014-01-06 18:52:12 -0500 |
| commit | 795449d8b846a42d11d47d6ff2f51ab2967411c3 (patch) | |
| tree | eeffc34bfce44f151761d61637bfa13f045c4bd6 /net/openvswitch | |
| parent | aae9f0e22c07f6b97752741156ac0b3637d37a1a (diff) | |
openvswitch: Enable memory mapped Netlink i/o
Use memory mapped Netlink i/o for all unicast openvswitch
communication if a ring has been set up.
Benchmark
* pktgen -> ovs internal port
* 5M pkts, 5M flows
* 4 threads, 8 cores
Before:
Result: OK: 67418743(c67108212+d310530) usec, 5000000 (9000byte,0frags)
74163pps 5339Mb/sec (5339736000bps) errors: 0
+ 2.98% ovs-vswitchd [k] copy_user_generic_string
+ 2.49% ovs-vswitchd [k] memcpy
+ 1.84% kpktgend_2 [k] memcpy
+ 1.81% kpktgend_1 [k] memcpy
+ 1.81% kpktgend_3 [k] memcpy
+ 1.78% kpktgend_0 [k] memcpy
After:
Result: OK: 24229690(c24127165+d102524) usec, 5000000 (9000byte,0frags)
206358pps 14857Mb/sec (14857776000bps) errors: 0
+ 2.80% ovs-vswitchd [k] memcpy
+ 1.31% kpktgend_2 [k] memcpy
+ 1.23% kpktgend_0 [k] memcpy
+ 1.09% kpktgend_1 [k] memcpy
+ 1.04% kpktgend_3 [k] memcpy
+ 0.96% ovs-vswitchd [k] copy_user_generic_string
Signed-off-by: Thomas Graf <tgraf@suug.ch>
Reviewed-by: Daniel Borkmann <dborkman@redhat.com>
Signed-off-by: Jesse Gross <jesse@nicira.com>
Diffstat (limited to 'net/openvswitch')
| -rw-r--r-- | net/openvswitch/datapath.c | 56 |
1 files changed, 29 insertions, 27 deletions
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 0727aaa2c825..5da2534b140a 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c | |||
| @@ -402,6 +402,11 @@ static int queue_userspace_packet(struct net *net, int dp_ifindex, | |||
| 402 | struct sk_buff *nskb = NULL; | 402 | struct sk_buff *nskb = NULL; |
| 403 | struct sk_buff *user_skb; /* to be queued to userspace */ | 403 | struct sk_buff *user_skb; /* to be queued to userspace */ |
| 404 | struct nlattr *nla; | 404 | struct nlattr *nla; |
| 405 | struct genl_info info = { | ||
| 406 | .dst_sk = net->genl_sock, | ||
| 407 | .snd_portid = upcall_info->portid, | ||
| 408 | }; | ||
| 409 | size_t len; | ||
| 405 | int err; | 410 | int err; |
| 406 | 411 | ||
| 407 | if (vlan_tx_tag_present(skb)) { | 412 | if (vlan_tx_tag_present(skb)) { |
| @@ -422,7 +427,8 @@ static int queue_userspace_packet(struct net *net, int dp_ifindex, | |||
| 422 | goto out; | 427 | goto out; |
| 423 | } | 428 | } |
| 424 | 429 | ||
| 425 | user_skb = genlmsg_new(upcall_msg_size(skb, upcall_info->userdata), GFP_ATOMIC); | 430 | len = upcall_msg_size(skb, upcall_info->userdata); |
| 431 | user_skb = genlmsg_new_unicast(len, &info, GFP_ATOMIC); | ||
| 426 | if (!user_skb) { | 432 | if (!user_skb) { |
| 427 | err = -ENOMEM; | 433 | err = -ENOMEM; |
| 428 | goto out; | 434 | goto out; |
| @@ -725,27 +731,30 @@ error: | |||
| 725 | return err; | 731 | return err; |
| 726 | } | 732 | } |
| 727 | 733 | ||
| 728 | static struct sk_buff *ovs_flow_cmd_alloc_info(struct sw_flow *flow) | 734 | static struct sk_buff *ovs_flow_cmd_alloc_info(struct sw_flow *flow, |
| 735 | struct genl_info *info) | ||
| 729 | { | 736 | { |
| 730 | const struct sw_flow_actions *sf_acts; | 737 | size_t len; |
| 731 | 738 | ||
| 732 | sf_acts = ovsl_dereference(flow->sf_acts); | 739 | len = ovs_flow_cmd_msg_size(ovsl_dereference(flow->sf_acts)); |
| 733 | 740 | ||
| 734 | return genlmsg_new(ovs_flow_cmd_msg_size(sf_acts), GFP_KERNEL); | 741 | return genlmsg_new_unicast(len, info, GFP_KERNEL); |
| 735 | } | 742 | } |
| 736 | 743 | ||
| 737 | static struct sk_buff *ovs_flow_cmd_build_info(struct sw_flow *flow, | 744 | static struct sk_buff *ovs_flow_cmd_build_info(struct sw_flow *flow, |
| 738 | struct datapath *dp, | 745 | struct datapath *dp, |
| 739 | u32 portid, u32 seq, u8 cmd) | 746 | struct genl_info *info, |
| 747 | u8 cmd) | ||
| 740 | { | 748 | { |
| 741 | struct sk_buff *skb; | 749 | struct sk_buff *skb; |
| 742 | int retval; | 750 | int retval; |
| 743 | 751 | ||
| 744 | skb = ovs_flow_cmd_alloc_info(flow); | 752 | skb = ovs_flow_cmd_alloc_info(flow, info); |
| 745 | if (!skb) | 753 | if (!skb) |
| 746 | return ERR_PTR(-ENOMEM); | 754 | return ERR_PTR(-ENOMEM); |
| 747 | 755 | ||
| 748 | retval = ovs_flow_cmd_fill_info(flow, dp, skb, portid, seq, 0, cmd); | 756 | retval = ovs_flow_cmd_fill_info(flow, dp, skb, info->snd_portid, |
| 757 | info->snd_seq, 0, cmd); | ||
| 749 | BUG_ON(retval < 0); | 758 | BUG_ON(retval < 0); |
| 750 | return skb; | 759 | return skb; |
| 751 | } | 760 | } |
| @@ -826,8 +835,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info) | |||
| 826 | goto err_flow_free; | 835 | goto err_flow_free; |
| 827 | } | 836 | } |
| 828 | 837 | ||
| 829 | reply = ovs_flow_cmd_build_info(flow, dp, info->snd_portid, | 838 | reply = ovs_flow_cmd_build_info(flow, dp, info, OVS_FLOW_CMD_NEW); |
| 830 | info->snd_seq, OVS_FLOW_CMD_NEW); | ||
| 831 | } else { | 839 | } else { |
| 832 | /* We found a matching flow. */ | 840 | /* We found a matching flow. */ |
| 833 | struct sw_flow_actions *old_acts; | 841 | struct sw_flow_actions *old_acts; |
| @@ -855,8 +863,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info) | |||
| 855 | rcu_assign_pointer(flow->sf_acts, acts); | 863 | rcu_assign_pointer(flow->sf_acts, acts); |
| 856 | ovs_nla_free_flow_actions(old_acts); | 864 | ovs_nla_free_flow_actions(old_acts); |
| 857 | 865 | ||
| 858 | reply = ovs_flow_cmd_build_info(flow, dp, info->snd_portid, | 866 | reply = ovs_flow_cmd_build_info(flow, dp, info, OVS_FLOW_CMD_NEW); |
| 859 | info->snd_seq, OVS_FLOW_CMD_NEW); | ||
| 860 | 867 | ||
| 861 | /* Clear stats. */ | 868 | /* Clear stats. */ |
| 862 | if (a[OVS_FLOW_ATTR_CLEAR]) { | 869 | if (a[OVS_FLOW_ATTR_CLEAR]) { |
| @@ -918,8 +925,7 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info) | |||
| 918 | goto unlock; | 925 | goto unlock; |
| 919 | } | 926 | } |
| 920 | 927 | ||
| 921 | reply = ovs_flow_cmd_build_info(flow, dp, info->snd_portid, | 928 | reply = ovs_flow_cmd_build_info(flow, dp, info, OVS_FLOW_CMD_NEW); |
| 922 | info->snd_seq, OVS_FLOW_CMD_NEW); | ||
| 923 | if (IS_ERR(reply)) { | 929 | if (IS_ERR(reply)) { |
| 924 | err = PTR_ERR(reply); | 930 | err = PTR_ERR(reply); |
| 925 | goto unlock; | 931 | goto unlock; |
| @@ -966,7 +972,7 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info) | |||
| 966 | goto unlock; | 972 | goto unlock; |
| 967 | } | 973 | } |
| 968 | 974 | ||
| 969 | reply = ovs_flow_cmd_alloc_info(flow); | 975 | reply = ovs_flow_cmd_alloc_info(flow, info); |
| 970 | if (!reply) { | 976 | if (!reply) { |
| 971 | err = -ENOMEM; | 977 | err = -ENOMEM; |
| 972 | goto unlock; | 978 | goto unlock; |
| @@ -1118,17 +1124,17 @@ error: | |||
| 1118 | return -EMSGSIZE; | 1124 | return -EMSGSIZE; |
| 1119 | } | 1125 | } |
| 1120 | 1126 | ||
| 1121 | static struct sk_buff *ovs_dp_cmd_build_info(struct datapath *dp, u32 portid, | 1127 | static struct sk_buff *ovs_dp_cmd_build_info(struct datapath *dp, |
| 1122 | u32 seq, u8 cmd) | 1128 | struct genl_info *info, u8 cmd) |
| 1123 | { | 1129 | { |
| 1124 | struct sk_buff *skb; | 1130 | struct sk_buff *skb; |
| 1125 | int retval; | 1131 | int retval; |
| 1126 | 1132 | ||
| 1127 | skb = genlmsg_new(ovs_dp_cmd_msg_size(), GFP_KERNEL); | 1133 | skb = genlmsg_new_unicast(ovs_dp_cmd_msg_size(), info, GFP_KERNEL); |
| 1128 | if (!skb) | 1134 | if (!skb) |
| 1129 | return ERR_PTR(-ENOMEM); | 1135 | return ERR_PTR(-ENOMEM); |
| 1130 | 1136 | ||
| 1131 | retval = ovs_dp_cmd_fill_info(dp, skb, portid, seq, 0, cmd); | 1137 | retval = ovs_dp_cmd_fill_info(dp, skb, info->snd_portid, info->snd_seq, 0, cmd); |
| 1132 | if (retval < 0) { | 1138 | if (retval < 0) { |
| 1133 | kfree_skb(skb); | 1139 | kfree_skb(skb); |
| 1134 | return ERR_PTR(retval); | 1140 | return ERR_PTR(retval); |
| @@ -1223,8 +1229,7 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info) | |||
| 1223 | goto err_destroy_ports_array; | 1229 | goto err_destroy_ports_array; |
| 1224 | } | 1230 | } |
| 1225 | 1231 | ||
| 1226 | reply = ovs_dp_cmd_build_info(dp, info->snd_portid, | 1232 | reply = ovs_dp_cmd_build_info(dp, info, OVS_DP_CMD_NEW); |
| 1227 | info->snd_seq, OVS_DP_CMD_NEW); | ||
| 1228 | err = PTR_ERR(reply); | 1233 | err = PTR_ERR(reply); |
| 1229 | if (IS_ERR(reply)) | 1234 | if (IS_ERR(reply)) |
| 1230 | goto err_destroy_local_port; | 1235 | goto err_destroy_local_port; |
| @@ -1290,8 +1295,7 @@ static int ovs_dp_cmd_del(struct sk_buff *skb, struct genl_info *info) | |||
| 1290 | if (IS_ERR(dp)) | 1295 | if (IS_ERR(dp)) |
| 1291 | goto unlock; | 1296 | goto unlock; |
| 1292 | 1297 | ||
| 1293 | reply = ovs_dp_cmd_build_info(dp, info->snd_portid, | 1298 | reply = ovs_dp_cmd_build_info(dp, info, OVS_DP_CMD_DEL); |
| 1294 | info->snd_seq, OVS_DP_CMD_DEL); | ||
| 1295 | err = PTR_ERR(reply); | 1299 | err = PTR_ERR(reply); |
| 1296 | if (IS_ERR(reply)) | 1300 | if (IS_ERR(reply)) |
| 1297 | goto unlock; | 1301 | goto unlock; |
| @@ -1319,8 +1323,7 @@ static int ovs_dp_cmd_set(struct sk_buff *skb, struct genl_info *info) | |||
| 1319 | if (IS_ERR(dp)) | 1323 | if (IS_ERR(dp)) |
| 1320 | goto unlock; | 1324 | goto unlock; |
| 1321 | 1325 | ||
| 1322 | reply = ovs_dp_cmd_build_info(dp, info->snd_portid, | 1326 | reply = ovs_dp_cmd_build_info(dp, info, OVS_DP_CMD_NEW); |
| 1323 | info->snd_seq, OVS_DP_CMD_NEW); | ||
| 1324 | if (IS_ERR(reply)) { | 1327 | if (IS_ERR(reply)) { |
| 1325 | err = PTR_ERR(reply); | 1328 | err = PTR_ERR(reply); |
| 1326 | genl_set_err(&dp_datapath_genl_family, sock_net(skb->sk), 0, | 1329 | genl_set_err(&dp_datapath_genl_family, sock_net(skb->sk), 0, |
| @@ -1351,8 +1354,7 @@ static int ovs_dp_cmd_get(struct sk_buff *skb, struct genl_info *info) | |||
| 1351 | goto unlock; | 1354 | goto unlock; |
| 1352 | } | 1355 | } |
| 1353 | 1356 | ||
| 1354 | reply = ovs_dp_cmd_build_info(dp, info->snd_portid, | 1357 | reply = ovs_dp_cmd_build_info(dp, info, OVS_DP_CMD_NEW); |
| 1355 | info->snd_seq, OVS_DP_CMD_NEW); | ||
| 1356 | if (IS_ERR(reply)) { | 1358 | if (IS_ERR(reply)) { |
| 1357 | err = PTR_ERR(reply); | 1359 | err = PTR_ERR(reply); |
| 1358 | goto unlock; | 1360 | goto unlock; |
