mirror of
https://github.com/openvswitch/ovs
synced 2025-08-31 14:25:26 +00:00
ofp-actions: Only set defined bits when encoding "load" actions.
Commit 7eb4b1f1d7
("ofp-actions: Support OF1.5 (draft) masked
Set-Field, merge with reg_load.") introduced a bug in that a set_field
action that set an entire field would be translated incorrectly to
reg_load, if the field being set only occupied a portion of the bytes that
it contains. For example, an MPLS label is 20 bits but has a 4-byte field,
which meant that a set_field would get translated into a reg_load that
wrote all 32 bits; in turn, the receiver of that reg_load would reject it
because it was attempting to set invalid bits (the top 12 bits).
This commit fixes the problem by omitting invalid bits when encoding a
reg_load action.
Reported-by: Pravin Shelar <pshelar@nicira.com>
Tested-by: Pravin Shelar <pshelar@nicira.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: YAMAMOTO Takashi <yamamoto@valinux.co.jp>
This commit is contained in:
@@ -2183,16 +2183,17 @@ static bool
|
||||
next_load_segment(const struct ofpact_set_field *sf,
|
||||
struct mf_subfield *dst, uint64_t *value)
|
||||
{
|
||||
int w = sf->field->n_bytes;
|
||||
int n_bits = sf->field->n_bits;
|
||||
int n_bytes = sf->field->n_bytes;
|
||||
int start = dst->ofs + dst->n_bits;
|
||||
|
||||
if (start < 8 * w) {
|
||||
if (start < n_bits) {
|
||||
dst->field = sf->field;
|
||||
dst->ofs = bitwise_scan(&sf->mask, w, 1, start, 8 * w);
|
||||
if (dst->ofs < 8 * w) {
|
||||
dst->n_bits = bitwise_scan(&sf->mask, w, 0, dst->ofs + 1,
|
||||
MIN(dst->ofs + 64, 8 * w)) - dst->ofs;
|
||||
*value = bitwise_get(&sf->value, w, dst->ofs, dst->n_bits);
|
||||
dst->ofs = bitwise_scan(&sf->mask, n_bytes, 1, start, n_bits);
|
||||
if (dst->ofs < n_bits) {
|
||||
dst->n_bits = bitwise_scan(&sf->mask, n_bytes, 0, dst->ofs + 1,
|
||||
MIN(dst->ofs + 64, n_bits)) - dst->ofs;
|
||||
*value = bitwise_get(&sf->value, n_bytes, dst->ofs, dst->n_bits);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user