aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorThomas Graf <tgraf@suug.ch>2013-03-29 09:46:49 -0400
committerJesse Gross <jesse@nicira.com>2013-03-29 20:53:57 -0400
commitc3ff8cfe3e7748a93c4815b76e464d54c7efd241 (patch)
tree4526700f7eda3334516e16076c0917c1bae5fbac /net
parent32686a9d2988516788cfcc402e1355c1eba1186a (diff)
openvswitch: Refine Netlink message size calculation and kill FLOW_BUFSIZE
Kills the FLOW_BUFSIZE constant which needs to be calculated manually and replaces it with key_attr_size() based on nla_total_size(). Calculates the size of datapath messages instead of relying on NLMSG_DEFAULT_SIZE and moves the existing message size calculations into own functions for clarity. Signed-off-by: Thomas Graf <tgraf@suug.ch> Signed-off-by: Jesse Gross <jesse@nicira.com>
Diffstat (limited to 'net')
-rw-r--r--net/openvswitch/datapath.c76
-rw-r--r--net/openvswitch/flow.h21
2 files changed, 52 insertions, 45 deletions
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index bca63c8487bb..49ee37b83a29 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -337,6 +337,35 @@ static int queue_gso_packets(struct net *net, int dp_ifindex,
337 return err; 337 return err;
338} 338}
339 339
340static size_t key_attr_size(void)
341{
342 return nla_total_size(4) /* OVS_KEY_ATTR_PRIORITY */
343 + nla_total_size(4) /* OVS_KEY_ATTR_IN_PORT */
344 + nla_total_size(4) /* OVS_KEY_ATTR_SKB_MARK */
345 + nla_total_size(12) /* OVS_KEY_ATTR_ETHERNET */
346 + nla_total_size(2) /* OVS_KEY_ATTR_ETHERTYPE */
347 + nla_total_size(4) /* OVS_KEY_ATTR_8021Q */
348 + nla_total_size(0) /* OVS_KEY_ATTR_ENCAP */
349 + nla_total_size(2) /* OVS_KEY_ATTR_ETHERTYPE */
350 + nla_total_size(40) /* OVS_KEY_ATTR_IPV6 */
351 + nla_total_size(2) /* OVS_KEY_ATTR_ICMPV6 */
352 + nla_total_size(28); /* OVS_KEY_ATTR_ND */
353}
354
355static size_t upcall_msg_size(const struct sk_buff *skb,
356 const struct nlattr *userdata)
357{
358 size_t size = NLMSG_ALIGN(sizeof(struct ovs_header))
359 + nla_total_size(skb->len) /* OVS_PACKET_ATTR_PACKET */
360 + nla_total_size(key_attr_size()); /* OVS_PACKET_ATTR_KEY */
361
362 /* OVS_PACKET_ATTR_USERDATA */
363 if (userdata)
364 size += NLA_ALIGN(userdata->nla_len);
365
366 return size;
367}
368
340static int queue_userspace_packet(struct net *net, int dp_ifindex, 369static int queue_userspace_packet(struct net *net, int dp_ifindex,
341 struct sk_buff *skb, 370 struct sk_buff *skb,
342 const struct dp_upcall_info *upcall_info) 371 const struct dp_upcall_info *upcall_info)
@@ -345,7 +374,6 @@ static int queue_userspace_packet(struct net *net, int dp_ifindex,
345 struct sk_buff *nskb = NULL; 374 struct sk_buff *nskb = NULL;
346 struct sk_buff *user_skb; /* to be queued to userspace */ 375 struct sk_buff *user_skb; /* to be queued to userspace */
347 struct nlattr *nla; 376 struct nlattr *nla;
348 unsigned int len;
349 int err; 377 int err;
350 378
351 if (vlan_tx_tag_present(skb)) { 379 if (vlan_tx_tag_present(skb)) {
@@ -366,13 +394,7 @@ static int queue_userspace_packet(struct net *net, int dp_ifindex,
366 goto out; 394 goto out;
367 } 395 }
368 396
369 len = sizeof(struct ovs_header); 397 user_skb = genlmsg_new(upcall_msg_size(skb, upcall_info->userdata), GFP_ATOMIC);
370 len += nla_total_size(skb->len);
371 len += nla_total_size(FLOW_BUFSIZE);
372 if (upcall_info->userdata)
373 len += NLA_ALIGN(upcall_info->userdata->nla_len);
374
375 user_skb = genlmsg_new(len, GFP_ATOMIC);
376 if (!user_skb) { 398 if (!user_skb) {
377 err = -ENOMEM; 399 err = -ENOMEM;
378 goto out; 400 goto out;
@@ -801,6 +823,16 @@ static struct genl_multicast_group ovs_dp_flow_multicast_group = {
801 .name = OVS_FLOW_MCGROUP 823 .name = OVS_FLOW_MCGROUP
802}; 824};
803 825
826static size_t ovs_flow_cmd_msg_size(const struct sw_flow_actions *acts)
827{
828 return NLMSG_ALIGN(sizeof(struct ovs_header))
829 + nla_total_size(key_attr_size()) /* OVS_FLOW_ATTR_KEY */
830 + nla_total_size(sizeof(struct ovs_flow_stats)) /* OVS_FLOW_ATTR_STATS */
831 + nla_total_size(1) /* OVS_FLOW_ATTR_TCP_FLAGS */
832 + nla_total_size(8) /* OVS_FLOW_ATTR_USED */
833 + nla_total_size(acts->actions_len); /* OVS_FLOW_ATTR_ACTIONS */
834}
835
804/* Called with genl_lock. */ 836/* Called with genl_lock. */
805static int ovs_flow_cmd_fill_info(struct sw_flow *flow, struct datapath *dp, 837static int ovs_flow_cmd_fill_info(struct sw_flow *flow, struct datapath *dp,
806 struct sk_buff *skb, u32 portid, 838 struct sk_buff *skb, u32 portid,
@@ -879,25 +911,11 @@ error:
879static struct sk_buff *ovs_flow_cmd_alloc_info(struct sw_flow *flow) 911static struct sk_buff *ovs_flow_cmd_alloc_info(struct sw_flow *flow)
880{ 912{
881 const struct sw_flow_actions *sf_acts; 913 const struct sw_flow_actions *sf_acts;
882 int len;
883 914
884 sf_acts = rcu_dereference_protected(flow->sf_acts, 915 sf_acts = rcu_dereference_protected(flow->sf_acts,
885 lockdep_genl_is_held()); 916 lockdep_genl_is_held());
886 917
887 /* OVS_FLOW_ATTR_KEY */ 918 return genlmsg_new(ovs_flow_cmd_msg_size(sf_acts), GFP_KERNEL);
888 len = nla_total_size(FLOW_BUFSIZE);
889 /* OVS_FLOW_ATTR_ACTIONS */
890 len += nla_total_size(sf_acts->actions_len);
891 /* OVS_FLOW_ATTR_STATS */
892 len += nla_total_size(sizeof(struct ovs_flow_stats));
893 /* OVS_FLOW_ATTR_TCP_FLAGS */
894 len += nla_total_size(1);
895 /* OVS_FLOW_ATTR_USED */
896 len += nla_total_size(8);
897
898 len += NLMSG_ALIGN(sizeof(struct ovs_header));
899
900 return genlmsg_new(len, GFP_KERNEL);
901} 919}
902 920
903static struct sk_buff *ovs_flow_cmd_build_info(struct sw_flow *flow, 921static struct sk_buff *ovs_flow_cmd_build_info(struct sw_flow *flow,
@@ -1213,6 +1231,16 @@ static struct genl_multicast_group ovs_dp_datapath_multicast_group = {
1213 .name = OVS_DATAPATH_MCGROUP 1231 .name = OVS_DATAPATH_MCGROUP
1214}; 1232};
1215 1233
1234static size_t ovs_dp_cmd_msg_size(void)
1235{
1236 size_t msgsize = NLMSG_ALIGN(sizeof(struct ovs_header));
1237
1238 msgsize += nla_total_size(IFNAMSIZ);
1239 msgsize += nla_total_size(sizeof(struct ovs_dp_stats));
1240
1241 return msgsize;
1242}
1243
1216static int ovs_dp_cmd_fill_info(struct datapath *dp, struct sk_buff *skb, 1244static int ovs_dp_cmd_fill_info(struct datapath *dp, struct sk_buff *skb,
1217 u32 portid, u32 seq, u32 flags, u8 cmd) 1245 u32 portid, u32 seq, u32 flags, u8 cmd)
1218{ 1246{
@@ -1251,7 +1279,7 @@ static struct sk_buff *ovs_dp_cmd_build_info(struct datapath *dp, u32 portid,
1251 struct sk_buff *skb; 1279 struct sk_buff *skb;
1252 int retval; 1280 int retval;
1253 1281
1254 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1282 skb = genlmsg_new(ovs_dp_cmd_msg_size(), GFP_KERNEL);
1255 if (!skb) 1283 if (!skb)
1256 return ERR_PTR(-ENOMEM); 1284 return ERR_PTR(-ENOMEM);
1257 1285
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h
index a7bb60ff3b5b..0875fde65b9c 100644
--- a/net/openvswitch/flow.h
+++ b/net/openvswitch/flow.h
@@ -138,27 +138,6 @@ int ovs_flow_extract(struct sk_buff *, u16 in_port, struct sw_flow_key *,
138void ovs_flow_used(struct sw_flow *, struct sk_buff *); 138void ovs_flow_used(struct sw_flow *, struct sk_buff *);
139u64 ovs_flow_used_time(unsigned long flow_jiffies); 139u64 ovs_flow_used_time(unsigned long flow_jiffies);
140 140
141/* Upper bound on the length of a nlattr-formatted flow key. The longest
142 * nlattr-formatted flow key would be:
143 *
144 * struct pad nl hdr total
145 * ------ --- ------ -----
146 * OVS_KEY_ATTR_PRIORITY 4 -- 4 8
147 * OVS_KEY_ATTR_IN_PORT 4 -- 4 8
148 * OVS_KEY_ATTR_SKB_MARK 4 -- 4 8
149 * OVS_KEY_ATTR_ETHERNET 12 -- 4 16
150 * OVS_KEY_ATTR_ETHERTYPE 2 2 4 8 (outer VLAN ethertype)
151 * OVS_KEY_ATTR_8021Q 4 -- 4 8
152 * OVS_KEY_ATTR_ENCAP 0 -- 4 4 (VLAN encapsulation)
153 * OVS_KEY_ATTR_ETHERTYPE 2 2 4 8 (inner VLAN ethertype)
154 * OVS_KEY_ATTR_IPV6 40 -- 4 44
155 * OVS_KEY_ATTR_ICMPV6 2 2 4 8
156 * OVS_KEY_ATTR_ND 28 -- 4 32
157 * -------------------------------------------------
158 * total 152
159 */
160#define FLOW_BUFSIZE 152
161
162int ovs_flow_to_nlattrs(const struct sw_flow_key *, struct sk_buff *); 141int ovs_flow_to_nlattrs(const struct sw_flow_key *, struct sk_buff *);
163int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp, 142int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
164 const struct nlattr *); 143 const struct nlattr *);