mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 16:54:21 +00:00 
			
		
		
		
	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>
This commit is contained in:
		
							parent
							
								
									32686a9d29
								
							
						
					
					
						commit
						c3ff8cfe3e
					
				
					 2 changed files with 52 additions and 45 deletions
				
			
		|  | @ -337,6 +337,35 @@ static int queue_gso_packets(struct net *net, int dp_ifindex, | ||||||
| 	return err; | 	return err; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static size_t key_attr_size(void) | ||||||
|  | { | ||||||
|  | 	return    nla_total_size(4)   /* OVS_KEY_ATTR_PRIORITY */ | ||||||
|  | 		+ nla_total_size(4)   /* OVS_KEY_ATTR_IN_PORT */ | ||||||
|  | 		+ nla_total_size(4)   /* OVS_KEY_ATTR_SKB_MARK */ | ||||||
|  | 		+ nla_total_size(12)  /* OVS_KEY_ATTR_ETHERNET */ | ||||||
|  | 		+ nla_total_size(2)   /* OVS_KEY_ATTR_ETHERTYPE */ | ||||||
|  | 		+ nla_total_size(4)   /* OVS_KEY_ATTR_8021Q */ | ||||||
|  | 		+ nla_total_size(0)   /* OVS_KEY_ATTR_ENCAP */ | ||||||
|  | 		+ nla_total_size(2)   /* OVS_KEY_ATTR_ETHERTYPE */ | ||||||
|  | 		+ nla_total_size(40)  /* OVS_KEY_ATTR_IPV6 */ | ||||||
|  | 		+ nla_total_size(2)   /* OVS_KEY_ATTR_ICMPV6 */ | ||||||
|  | 		+ nla_total_size(28); /* OVS_KEY_ATTR_ND */ | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static size_t upcall_msg_size(const struct sk_buff *skb, | ||||||
|  | 			      const struct nlattr *userdata) | ||||||
|  | { | ||||||
|  | 	size_t size = NLMSG_ALIGN(sizeof(struct ovs_header)) | ||||||
|  | 		+ nla_total_size(skb->len) /* OVS_PACKET_ATTR_PACKET */ | ||||||
|  | 		+ nla_total_size(key_attr_size()); /* OVS_PACKET_ATTR_KEY */ | ||||||
|  | 
 | ||||||
|  | 	/* OVS_PACKET_ATTR_USERDATA */ | ||||||
|  | 	if (userdata) | ||||||
|  | 		size += NLA_ALIGN(userdata->nla_len); | ||||||
|  | 
 | ||||||
|  | 	return size; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static int queue_userspace_packet(struct net *net, int dp_ifindex, | static int queue_userspace_packet(struct net *net, int dp_ifindex, | ||||||
| 				  struct sk_buff *skb, | 				  struct sk_buff *skb, | ||||||
| 				  const struct dp_upcall_info *upcall_info) | 				  const struct dp_upcall_info *upcall_info) | ||||||
|  | @ -345,7 +374,6 @@ static int queue_userspace_packet(struct net *net, int dp_ifindex, | ||||||
| 	struct sk_buff *nskb = NULL; | 	struct sk_buff *nskb = NULL; | ||||||
| 	struct sk_buff *user_skb; /* to be queued to userspace */ | 	struct sk_buff *user_skb; /* to be queued to userspace */ | ||||||
| 	struct nlattr *nla; | 	struct nlattr *nla; | ||||||
| 	unsigned int len; |  | ||||||
| 	int err; | 	int err; | ||||||
| 
 | 
 | ||||||
| 	if (vlan_tx_tag_present(skb)) { | 	if (vlan_tx_tag_present(skb)) { | ||||||
|  | @ -366,13 +394,7 @@ static int queue_userspace_packet(struct net *net, int dp_ifindex, | ||||||
| 		goto out; | 		goto out; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	len = sizeof(struct ovs_header); | 	user_skb = genlmsg_new(upcall_msg_size(skb, upcall_info->userdata), GFP_ATOMIC); | ||||||
| 	len += nla_total_size(skb->len); |  | ||||||
| 	len += nla_total_size(FLOW_BUFSIZE); |  | ||||||
| 	if (upcall_info->userdata) |  | ||||||
| 		len += NLA_ALIGN(upcall_info->userdata->nla_len); |  | ||||||
| 
 |  | ||||||
| 	user_skb = genlmsg_new(len, GFP_ATOMIC); |  | ||||||
| 	if (!user_skb) { | 	if (!user_skb) { | ||||||
| 		err = -ENOMEM; | 		err = -ENOMEM; | ||||||
| 		goto out; | 		goto out; | ||||||
|  | @ -801,6 +823,16 @@ static struct genl_multicast_group ovs_dp_flow_multicast_group = { | ||||||
| 	.name = OVS_FLOW_MCGROUP | 	.name = OVS_FLOW_MCGROUP | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | static size_t ovs_flow_cmd_msg_size(const struct sw_flow_actions *acts) | ||||||
|  | { | ||||||
|  | 	return NLMSG_ALIGN(sizeof(struct ovs_header)) | ||||||
|  | 		+ nla_total_size(key_attr_size()) /* OVS_FLOW_ATTR_KEY */ | ||||||
|  | 		+ nla_total_size(sizeof(struct ovs_flow_stats)) /* OVS_FLOW_ATTR_STATS */ | ||||||
|  | 		+ nla_total_size(1) /* OVS_FLOW_ATTR_TCP_FLAGS */ | ||||||
|  | 		+ nla_total_size(8) /* OVS_FLOW_ATTR_USED */ | ||||||
|  | 		+ nla_total_size(acts->actions_len); /* OVS_FLOW_ATTR_ACTIONS */ | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /* Called with genl_lock. */ | /* Called with genl_lock. */ | ||||||
| static int ovs_flow_cmd_fill_info(struct sw_flow *flow, struct datapath *dp, | static int ovs_flow_cmd_fill_info(struct sw_flow *flow, struct datapath *dp, | ||||||
| 				  struct sk_buff *skb, u32 portid, | 				  struct sk_buff *skb, u32 portid, | ||||||
|  | @ -879,25 +911,11 @@ error: | ||||||
| static struct sk_buff *ovs_flow_cmd_alloc_info(struct sw_flow *flow) | static struct sk_buff *ovs_flow_cmd_alloc_info(struct sw_flow *flow) | ||||||
| { | { | ||||||
| 	const struct sw_flow_actions *sf_acts; | 	const struct sw_flow_actions *sf_acts; | ||||||
| 	int len; |  | ||||||
| 
 | 
 | ||||||
| 	sf_acts = rcu_dereference_protected(flow->sf_acts, | 	sf_acts = rcu_dereference_protected(flow->sf_acts, | ||||||
| 					    lockdep_genl_is_held()); | 					    lockdep_genl_is_held()); | ||||||
| 
 | 
 | ||||||
| 	/* OVS_FLOW_ATTR_KEY */ | 	return genlmsg_new(ovs_flow_cmd_msg_size(sf_acts), GFP_KERNEL); | ||||||
| 	len = nla_total_size(FLOW_BUFSIZE); |  | ||||||
| 	/* OVS_FLOW_ATTR_ACTIONS */ |  | ||||||
| 	len += nla_total_size(sf_acts->actions_len); |  | ||||||
| 	/* OVS_FLOW_ATTR_STATS */ |  | ||||||
| 	len += nla_total_size(sizeof(struct ovs_flow_stats)); |  | ||||||
| 	/* OVS_FLOW_ATTR_TCP_FLAGS */ |  | ||||||
| 	len += nla_total_size(1); |  | ||||||
| 	/* OVS_FLOW_ATTR_USED */ |  | ||||||
| 	len += nla_total_size(8); |  | ||||||
| 
 |  | ||||||
| 	len += NLMSG_ALIGN(sizeof(struct ovs_header)); |  | ||||||
| 
 |  | ||||||
| 	return genlmsg_new(len, GFP_KERNEL); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static struct sk_buff *ovs_flow_cmd_build_info(struct sw_flow *flow, | static 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 = { | ||||||
| 	.name = OVS_DATAPATH_MCGROUP | 	.name = OVS_DATAPATH_MCGROUP | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | static size_t ovs_dp_cmd_msg_size(void) | ||||||
|  | { | ||||||
|  | 	size_t msgsize = NLMSG_ALIGN(sizeof(struct ovs_header)); | ||||||
|  | 
 | ||||||
|  | 	msgsize += nla_total_size(IFNAMSIZ); | ||||||
|  | 	msgsize += nla_total_size(sizeof(struct ovs_dp_stats)); | ||||||
|  | 
 | ||||||
|  | 	return msgsize; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static int ovs_dp_cmd_fill_info(struct datapath *dp, struct sk_buff *skb, | static int ovs_dp_cmd_fill_info(struct datapath *dp, struct sk_buff *skb, | ||||||
| 				u32 portid, u32 seq, u32 flags, u8 cmd) | 				u32 portid, u32 seq, u32 flags, u8 cmd) | ||||||
| { | { | ||||||
|  | @ -1251,7 +1279,7 @@ static struct sk_buff *ovs_dp_cmd_build_info(struct datapath *dp, u32 portid, | ||||||
| 	struct sk_buff *skb; | 	struct sk_buff *skb; | ||||||
| 	int retval; | 	int retval; | ||||||
| 
 | 
 | ||||||
| 	skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 	skb = genlmsg_new(ovs_dp_cmd_msg_size(), GFP_KERNEL); | ||||||
| 	if (!skb) | 	if (!skb) | ||||||
| 		return ERR_PTR(-ENOMEM); | 		return ERR_PTR(-ENOMEM); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -138,27 +138,6 @@ int ovs_flow_extract(struct sk_buff *, u16 in_port, struct sw_flow_key *, | ||||||
| void ovs_flow_used(struct sw_flow *, struct sk_buff *); | void ovs_flow_used(struct sw_flow *, struct sk_buff *); | ||||||
| u64 ovs_flow_used_time(unsigned long flow_jiffies); | u64 ovs_flow_used_time(unsigned long flow_jiffies); | ||||||
| 
 | 
 | ||||||
| /* Upper bound on the length of a nlattr-formatted flow key.  The longest
 |  | ||||||
|  * nlattr-formatted flow key would be: |  | ||||||
|  * |  | ||||||
|  *                         struct  pad  nl hdr  total |  | ||||||
|  *                         ------  ---  ------  ----- |  | ||||||
|  *  OVS_KEY_ATTR_PRIORITY      4    --     4      8 |  | ||||||
|  *  OVS_KEY_ATTR_IN_PORT       4    --     4      8 |  | ||||||
|  *  OVS_KEY_ATTR_SKB_MARK      4    --     4      8 |  | ||||||
|  *  OVS_KEY_ATTR_ETHERNET     12    --     4     16 |  | ||||||
|  *  OVS_KEY_ATTR_ETHERTYPE     2     2     4      8  (outer VLAN ethertype) |  | ||||||
|  *  OVS_KEY_ATTR_8021Q         4    --     4      8 |  | ||||||
|  *  OVS_KEY_ATTR_ENCAP         0    --     4      4  (VLAN encapsulation) |  | ||||||
|  *  OVS_KEY_ATTR_ETHERTYPE     2     2     4      8  (inner VLAN ethertype) |  | ||||||
|  *  OVS_KEY_ATTR_IPV6         40    --     4     44 |  | ||||||
|  *  OVS_KEY_ATTR_ICMPV6        2     2     4      8 |  | ||||||
|  *  OVS_KEY_ATTR_ND           28    --     4     32 |  | ||||||
|  *  ------------------------------------------------- |  | ||||||
|  *  total                                       152 |  | ||||||
|  */ |  | ||||||
| #define FLOW_BUFSIZE 152 |  | ||||||
| 
 |  | ||||||
| int ovs_flow_to_nlattrs(const struct sw_flow_key *, struct sk_buff *); | int ovs_flow_to_nlattrs(const struct sw_flow_key *, struct sk_buff *); | ||||||
| int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp, | int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp, | ||||||
| 		      const struct nlattr *); | 		      const struct nlattr *); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Thomas Graf
						Thomas Graf