mirror of
https://github.com/openvswitch/ovs
synced 2025-10-17 14:28:02 +00:00
datapath: backport: ovs: align nlattr properly when needed
Upstream commit: commit 66c7a5ee1a6b7c69d41dfd68d207fdd54efba56a Author: Nicolas Dichtel <nicolas.dichtel@6wind.com> ovs: align nlattr properly when needed I also fix commit 8b32ab9e6ef1: use nla_total_size_64bit() for OVS_FLOW_ATTR_USED in ovs_flow_cmd_msg_size(). Fixes: 8b32ab9e6ef1 ("ovs: use nla_put_u64_64bit()") Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Pravin B Shelar <pshelar@ovn.org> Acked-by: Jesse Gross <jesse@kernel.org>
This commit is contained in:
@@ -595,6 +595,7 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [
|
||||
OVS_GREP_IFELSE([$KSRC/include/net/ip6_route.h], [ip6_frag.*sock],
|
||||
[OVS_DEFINE([HAVE_IP_FRAGMENT_TAKES_SOCK])])
|
||||
|
||||
OVS_GREP_IFELSE([$KSRC/include/net/netlink.h], [nla_put_64bit])
|
||||
OVS_GREP_IFELSE([$KSRC/include/net/netlink.h], [nla_get_be16])
|
||||
OVS_GREP_IFELSE([$KSRC/include/net/netlink.h], [nla_put_be16])
|
||||
OVS_GREP_IFELSE([$KSRC/include/net/netlink.h], [nla_put_be32])
|
||||
|
@@ -771,9 +771,9 @@ static size_t ovs_flow_cmd_msg_size(const struct sw_flow_actions *acts,
|
||||
len += nla_total_size(acts->orig_len);
|
||||
|
||||
return len
|
||||
+ nla_total_size(sizeof(struct ovs_flow_stats)) /* OVS_FLOW_ATTR_STATS */
|
||||
+ nla_total_size_64bit(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_64bit(8); /* OVS_FLOW_ATTR_USED */
|
||||
}
|
||||
|
||||
/* Called with ovs_mutex or RCU read lock. */
|
||||
@@ -791,7 +791,9 @@ static int ovs_flow_cmd_fill_stats(const struct sw_flow *flow,
|
||||
return -EMSGSIZE;
|
||||
|
||||
if (stats.n_packets &&
|
||||
nla_put(skb, OVS_FLOW_ATTR_STATS, sizeof(struct ovs_flow_stats), &stats))
|
||||
nla_put_64bit(skb, OVS_FLOW_ATTR_STATS,
|
||||
sizeof(struct ovs_flow_stats), &stats,
|
||||
OVS_FLOW_ATTR_PAD))
|
||||
return -EMSGSIZE;
|
||||
|
||||
if ((u8)ntohs(tcp_flags) &&
|
||||
@@ -1470,8 +1472,8 @@ 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));
|
||||
msgsize += nla_total_size(sizeof(struct ovs_dp_megaflow_stats));
|
||||
msgsize += nla_total_size_64bit(sizeof(struct ovs_dp_stats));
|
||||
msgsize += nla_total_size_64bit(sizeof(struct ovs_dp_megaflow_stats));
|
||||
msgsize += nla_total_size(sizeof(u32)); /* OVS_DP_ATTR_USER_FEATURES */
|
||||
|
||||
return msgsize;
|
||||
@@ -1498,13 +1500,13 @@ static int ovs_dp_cmd_fill_info(struct datapath *dp, struct sk_buff *skb,
|
||||
goto nla_put_failure;
|
||||
|
||||
get_dp_stats(dp, &dp_stats, &dp_megaflow_stats);
|
||||
if (nla_put(skb, OVS_DP_ATTR_STATS, sizeof(struct ovs_dp_stats),
|
||||
&dp_stats))
|
||||
if (nla_put_64bit(skb, OVS_DP_ATTR_STATS, sizeof(struct ovs_dp_stats),
|
||||
&dp_stats, OVS_DP_ATTR_PAD))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (nla_put(skb, OVS_DP_ATTR_MEGAFLOW_STATS,
|
||||
sizeof(struct ovs_dp_megaflow_stats),
|
||||
&dp_megaflow_stats))
|
||||
if (nla_put_64bit(skb, OVS_DP_ATTR_MEGAFLOW_STATS,
|
||||
sizeof(struct ovs_dp_megaflow_stats),
|
||||
&dp_megaflow_stats, OVS_DP_ATTR_PAD))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (nla_put_u32(skb, OVS_DP_ATTR_USER_FEATURES, dp->user_features))
|
||||
@@ -1872,8 +1874,9 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb,
|
||||
goto nla_put_failure;
|
||||
|
||||
ovs_vport_get_stats(vport, &vport_stats);
|
||||
if (nla_put(skb, OVS_VPORT_ATTR_STATS, sizeof(struct ovs_vport_stats),
|
||||
&vport_stats))
|
||||
if (nla_put_64bit(skb, OVS_VPORT_ATTR_STATS,
|
||||
sizeof(struct ovs_vport_stats), &vport_stats,
|
||||
OVS_VPORT_ATTR_PAD))
|
||||
goto nla_put_failure;
|
||||
|
||||
if (ovs_vport_get_upcall_portids(vport, skb))
|
||||
|
@@ -104,6 +104,7 @@ enum ovs_datapath_attr {
|
||||
OVS_DP_ATTR_STATS, /* struct ovs_dp_stats */
|
||||
OVS_DP_ATTR_MEGAFLOW_STATS, /* struct ovs_dp_megaflow_stats */
|
||||
OVS_DP_ATTR_USER_FEATURES, /* OVS_DP_F_* */
|
||||
OVS_DP_ATTR_PAD,
|
||||
__OVS_DP_ATTR_MAX
|
||||
};
|
||||
|
||||
@@ -281,6 +282,7 @@ enum ovs_vport_attr {
|
||||
OVS_VPORT_ATTR_UPCALL_PID, /* array of u32 Netlink socket PIDs for */
|
||||
/* receiving upcalls */
|
||||
OVS_VPORT_ATTR_STATS, /* struct ovs_vport_stats */
|
||||
OVS_VPORT_ATTR_PAD,
|
||||
__OVS_VPORT_ATTR_MAX
|
||||
};
|
||||
|
||||
@@ -544,6 +546,7 @@ enum ovs_flow_attr {
|
||||
* logging should be suppressed. */
|
||||
OVS_FLOW_ATTR_UFID, /* Variable length unique flow identifier. */
|
||||
OVS_FLOW_ATTR_UFID_FLAGS,/* u32 of OVS_UFID_F_*. */
|
||||
OVS_FLOW_ATTR_PAD,
|
||||
__OVS_FLOW_ATTR_MAX
|
||||
};
|
||||
|
||||
|
@@ -98,4 +98,49 @@ static inline struct in6_addr nla_get_in6_addr(const struct nlattr *nla)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_NLA_PUT_64BIT
|
||||
static inline bool nla_need_padding_for_64bit(struct sk_buff *skb)
|
||||
{
|
||||
#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
|
||||
/* The nlattr header is 4 bytes in size, that's why we test
|
||||
* if the skb->data _is_ aligned. A NOP attribute, plus
|
||||
* nlattr header for next attribute, will make nla_data()
|
||||
* 8-byte aligned.
|
||||
*/
|
||||
if (IS_ALIGNED((unsigned long)skb_tail_pointer(skb), 8))
|
||||
return true;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline int nla_align_64bit(struct sk_buff *skb, int padattr)
|
||||
{
|
||||
if (nla_need_padding_for_64bit(skb) &&
|
||||
!nla_reserve(skb, padattr, 0))
|
||||
return -EMSGSIZE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int nla_total_size_64bit(int payload)
|
||||
{
|
||||
return NLA_ALIGN(nla_attr_size(payload))
|
||||
#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
|
||||
+ NLA_ALIGN(nla_attr_size(0))
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
#define nla_put_64bit rpl_nla_put_64bit
|
||||
int rpl_nla_put_64bit(struct sk_buff *skb, int attrtype, int attrlen,
|
||||
const void *data, int padattr);
|
||||
|
||||
#define __nla_put_64bit rpl___nla_put_64bit
|
||||
void rpl___nla_put_64bit(struct sk_buff *skb, int attrtype, int attrlen,
|
||||
const void *data, int padattr);
|
||||
|
||||
#define __nla_reserve_64bit rpl___nla_reserve_64bit
|
||||
struct nlattr *rpl___nla_reserve_64bit(struct sk_buff *skb, int attrtype,
|
||||
int attrlen, int padattr);
|
||||
#endif
|
||||
#endif /* net/netlink.h */
|
||||
|
@@ -93,3 +93,42 @@ void __percpu *__alloc_percpu_gfp(size_t size, size_t align, gfp_t gfp)
|
||||
return p;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_NLA_PUT_64BIT
|
||||
int rpl_nla_put_64bit(struct sk_buff *skb, int attrtype, int attrlen,
|
||||
const void *data, int padattr)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
if (nla_need_padding_for_64bit(skb))
|
||||
len = nla_total_size_64bit(attrlen);
|
||||
else
|
||||
len = nla_total_size(attrlen);
|
||||
if (unlikely(skb_tailroom(skb) < len))
|
||||
return -EMSGSIZE;
|
||||
|
||||
__nla_put_64bit(skb, attrtype, attrlen, data, padattr);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rpl_nla_put_64bit);
|
||||
|
||||
void rpl___nla_put_64bit(struct sk_buff *skb, int attrtype, int attrlen,
|
||||
const void *data, int padattr)
|
||||
{
|
||||
struct nlattr *nla;
|
||||
|
||||
nla = __nla_reserve_64bit(skb, attrtype, attrlen, padattr);
|
||||
memcpy(nla_data(nla), data, attrlen);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rpl___nla_put_64bit);
|
||||
|
||||
struct nlattr *rpl___nla_reserve_64bit(struct sk_buff *skb, int attrtype,
|
||||
int attrlen, int padattr)
|
||||
{
|
||||
if (nla_need_padding_for_64bit(skb))
|
||||
nla_align_64bit(skb, padattr);
|
||||
|
||||
return __nla_reserve(skb, attrtype, attrlen);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rpl___nla_reserve_64bit);
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user