mirror of
https://github.com/openvswitch/ovs
synced 2025-08-31 22:35:15 +00:00
ofproto-dpif-xlate: Suppress oversize datapath actions.
If we allow oversize datapath actions to make it out of translation, then we will assert-fail later when we try to put those actions into a Netlink attribute. Bug #19277. Reported-by: Paul ingram <paul@nicira.com> Signed-off-by: Ben Pfaff <blp@nicira.com> Acked-by: Justin Pettit <jpettit@nicira.com>
This commit is contained in:
@@ -322,7 +322,7 @@ nl_msg_push_unspec_uninit(struct ofpbuf *msg, uint16_t type, size_t size)
|
||||
{
|
||||
size_t total_size = NLA_HDRLEN + size;
|
||||
struct nlattr* nla = nl_msg_push_uninit(msg, total_size);
|
||||
ovs_assert(NLA_ALIGN(total_size) <= UINT16_MAX);
|
||||
ovs_assert(!nl_attr_oversized(size));
|
||||
nla->nla_len = total_size;
|
||||
nla->nla_type = type;
|
||||
return nla + 1;
|
||||
@@ -468,6 +468,16 @@ nl_msg_next(struct ofpbuf *buffer, struct ofpbuf *msg)
|
||||
msg->size = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Returns true if a Netlink attribute with a payload that is 'payload_size'
|
||||
* bytes long would be oversized, that is, if it's not possible to create an
|
||||
* nlattr of that size because its size wouldn't fit in the 16-bit nla_len
|
||||
* field. */
|
||||
bool
|
||||
nl_attr_oversized(size_t payload_size)
|
||||
{
|
||||
return NL_ATTR_SIZE(payload_size) > UINT16_MAX;
|
||||
}
|
||||
|
||||
/* Attributes. */
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2009, 2010, 2011 Nicira, Inc.
|
||||
* Copyright (c) 2008, 2009, 2010, 2011, 2013 Nicira, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -103,6 +103,8 @@ struct nlmsghdr *nl_msg_next(struct ofpbuf *buffer, struct ofpbuf *msg);
|
||||
#define NL_A_BE32_SIZE NL_ATTR_SIZE(sizeof(ovs_be32))
|
||||
#define NL_A_BE64_SIZE NL_ATTR_SIZE(sizeof(ovs_be64))
|
||||
#define NL_A_FLAG_SIZE NL_ATTR_SIZE(0)
|
||||
|
||||
bool nl_attr_oversized(size_t payload_size);
|
||||
|
||||
/* Netlink attribute types. */
|
||||
enum nl_attr_type
|
||||
|
@@ -2808,6 +2808,15 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout)
|
||||
}
|
||||
}
|
||||
|
||||
if (nl_attr_oversized(ctx.xout->odp_actions.size)) {
|
||||
/* These datapath actions are too big for a Netlink attribute, so we
|
||||
* can't execute them. */
|
||||
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1);
|
||||
|
||||
VLOG_ERR_RL(&rl, "discarding oversize datapath actions");
|
||||
ofpbuf_clear(&ctx.xout->odp_actions);
|
||||
}
|
||||
|
||||
ofpbuf_uninit(&ctx.stack);
|
||||
|
||||
/* Clear the metadata and register wildcard masks, because we won't
|
||||
|
@@ -2914,11 +2914,14 @@ ADD_OF_PORTS([br0], 1)
|
||||
echo "in_port=$i, actions=resubmit:$j, resubmit:$j, local"
|
||||
done
|
||||
echo "in_port=13, actions=local,local,local,local,local,local,local,local") > flows
|
||||
AT_CHECK([ovs-ofctl add-flows br0 flows])
|
||||
AT_CHECK([ovs-ofctl add-flows br0 flows])
|
||||
AT_CHECK([ovs-appctl ofproto/trace br0 'in_port=1'], [0], [stdout])
|
||||
AT_CHECK([grep -c 'resubmits yielded over 64 kB of actions' ovs-vswitchd.log], [0], [1
|
||||
])
|
||||
OVS_VSWITCHD_STOP(["/resubmits yielded over 64 kB of actions/d"])
|
||||
AT_CHECK([grep -c 'discarding oversize datapath actions' ovs-vswitchd.log], [0], [1
|
||||
])
|
||||
OVS_VSWITCHD_STOP(["/resubmits yielded over 64 kB of actions/d
|
||||
/discarding oversize datapath actions/d"])
|
||||
AT_CLEANUP
|
||||
|
||||
AT_SETUP([ofproto-dpif - stack too deep])
|
||||
|
Reference in New Issue
Block a user