mirror of
https://github.com/openbsd/src.git
synced 2024-12-22 07:27:59 -08:00
OpenFlow 1.3 defines packet header patterns of interest using TLVs (OXMs)
that represent various header fields. One place where OXMs are used is in the sef_field action, which contains one OXM representing the header field to set, followed by padding to align the action in the OpenFlow message to 64 bits. Currently, we assume that a set_field action can contain multiple OXMs and that they do not need to be padded. This matches the way we handle OpenFlow messages that contain set_field actions so that we follow the specs. OK ori claudio
This commit is contained in:
parent
5350a25a99
commit
c74ea87129
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: switchofp.c,v 1.75 2019/11/21 17:24:15 akoshibe Exp $ */
|
||||
/* $OpenBSD: switchofp.c,v 1.76 2019/11/27 17:37:32 akoshibe Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016 Kazuya GODA <goda@openbsd.org>
|
||||
@ -2174,7 +2174,8 @@ swofp_validate_action(struct switch_softc *sc, struct ofp_action_header *ah,
|
||||
}
|
||||
break;
|
||||
case OFP_ACTION_SET_FIELD:
|
||||
if (ahlen < sizeof(struct ofp_action_set_field)) {
|
||||
if (ahlen < sizeof(struct ofp_action_set_field) ||
|
||||
ahlen != OFP_ALIGN(ahlen)) {
|
||||
*err = OFP_ERRACTION_LEN;
|
||||
return (-1);
|
||||
}
|
||||
@ -2189,22 +2190,37 @@ swofp_validate_action(struct switch_softc *sc, struct ofp_action_header *ah,
|
||||
dptr = (uint8_t *)ah;
|
||||
dptr += sizeof(struct ofp_action_set_field) -
|
||||
offsetof(struct ofp_action_set_field, asf_field);
|
||||
while (oxmlen > 0) {
|
||||
oxm = (struct ofp_ox_match *)dptr;
|
||||
if (swofp_validate_oxm(oxm, err)) {
|
||||
if (*err == OFP_ERRMATCH_BAD_LEN)
|
||||
*err = OFP_ERRACTION_SET_LEN;
|
||||
else
|
||||
*err = OFP_ERRACTION_SET_TYPE;
|
||||
oxm = (struct ofp_ox_match *)dptr;
|
||||
oxmlen -= sizeof(struct ofp_ox_match);
|
||||
if (oxmlen < oxm->oxm_length) {
|
||||
*err = OFP_ERRACTION_SET_LEN;
|
||||
return (-1);
|
||||
}
|
||||
/* Remainder is padding. */
|
||||
oxmlen -= oxm->oxm_length;
|
||||
if (oxmlen >= OFP_ALIGNMENT) {
|
||||
*err = OFP_ERRACTION_SET_LEN;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (swofp_validate_oxm(oxm, err)) {
|
||||
if (*err == OFP_ERRMATCH_BAD_LEN)
|
||||
*err = OFP_ERRACTION_SET_LEN;
|
||||
else
|
||||
*err = OFP_ERRACTION_SET_TYPE;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
dptr += sizeof(struct ofp_ox_match) + oxm->oxm_length;
|
||||
while (oxmlen > 0) {
|
||||
if (*dptr != 0) {
|
||||
*err = OFP_ERRACTION_SET_ARGUMENT;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
dptr += sizeof(*oxm) + oxm->oxm_length;
|
||||
oxmlen -= sizeof(*oxm) + oxm->oxm_length;
|
||||
oxmlen--;
|
||||
dptr++;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Unknown/unsupported action. */
|
||||
*err = OFP_ERRACTION_TYPE;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: ofp13.c,v 1.46 2019/11/21 06:22:57 akoshibe Exp $ */
|
||||
/* $OpenBSD: ofp13.c,v 1.47 2019/11/27 17:37:32 akoshibe Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2013-2016 Reyk Floeter <reyk@openbsd.org>
|
||||
@ -780,7 +780,7 @@ ofp13_validate_action(struct switchd *sc, struct ofp_header *oh,
|
||||
print_map(type, ofp_action_map), len, ant->ant_ttl);
|
||||
break;
|
||||
case OFP_ACTION_SET_FIELD:
|
||||
if (len < sizeof(*asf))
|
||||
if (len < sizeof(*asf) || len != OFP_ALIGN(len))
|
||||
return (-1);
|
||||
if ((asf = ibuf_seek(ibuf, *off, sizeof(*asf))) == NULL)
|
||||
return (-1);
|
||||
@ -791,16 +791,14 @@ ofp13_validate_action(struct switchd *sc, struct ofp_header *oh,
|
||||
print_map(type, ofp_action_map), len);
|
||||
|
||||
len -= sizeof(*asf) - sizeof(asf->asf_field);
|
||||
while (len > 0) {
|
||||
if ((oxm = ibuf_seek(ibuf, moff, sizeof(*oxm)))
|
||||
== NULL)
|
||||
return (-1);
|
||||
if (ofp13_validate_oxm(sc, oxm, oh, ibuf, moff) == -1)
|
||||
return (-1);
|
||||
if ((oxm = ibuf_seek(ibuf, moff, sizeof(*oxm))) == NULL)
|
||||
return (-1);
|
||||
if (ofp13_validate_oxm(sc, oxm, oh, ibuf, moff) == -1)
|
||||
return (-1);
|
||||
|
||||
len -= sizeof(*oxm) + oxm->oxm_length;
|
||||
moff += sizeof(*oxm) + oxm->oxm_length;
|
||||
}
|
||||
len -= sizeof(*oxm) + oxm->oxm_length;
|
||||
if (len >= OFP_ALIGNMENT)
|
||||
return (-1);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: print-ofp.c,v 1.11 2016/11/28 17:47:15 jca Exp $ */
|
||||
/* $OpenBSD: print-ofp.c,v 1.12 2019/11/27 17:37:32 akoshibe Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016 Rafael Zalamena <rzalamena@openbsd.org>
|
||||
@ -231,11 +231,40 @@ ofp_print_setconfig(const u_char *bp, u_int length)
|
||||
ofp_controller_maxlen_map));
|
||||
}
|
||||
|
||||
void
|
||||
ofp_print_oxm_field(const u_char *bp, u_int length, int omlen, int once)
|
||||
{
|
||||
struct ofp_ox_match *oxm;
|
||||
|
||||
do {
|
||||
if (length < sizeof(*oxm)) {
|
||||
printf(" [|OpenFlow]");
|
||||
return;
|
||||
}
|
||||
|
||||
oxm = (struct ofp_ox_match *)bp;
|
||||
bp += sizeof(*oxm);
|
||||
length -= sizeof(*oxm);
|
||||
if (length < oxm->oxm_length) {
|
||||
printf(" [|OpenFlow]");
|
||||
return;
|
||||
}
|
||||
|
||||
ofp_print_oxm(oxm, bp, length);
|
||||
bp += oxm->oxm_length;
|
||||
length -= oxm->oxm_length;
|
||||
|
||||
if (once)
|
||||
return;
|
||||
|
||||
omlen -= min(sizeof(*oxm) + oxm->oxm_length, omlen);
|
||||
} while (omlen > 0);
|
||||
}
|
||||
|
||||
void
|
||||
ofp_print_packetin(const u_char *bp, u_int length)
|
||||
{
|
||||
struct ofp_packet_in *pin;
|
||||
struct ofp_ox_match *oxm;
|
||||
int omtype, omlen;
|
||||
int haspacket = 0;
|
||||
const u_char *pktptr;
|
||||
@ -276,27 +305,7 @@ ofp_print_packetin(const u_char *bp, u_int length)
|
||||
if (omlen == 0)
|
||||
goto print_packet;
|
||||
|
||||
parse_next_oxm:
|
||||
if (length < sizeof(*oxm)) {
|
||||
printf(" [|OpenFlow]");
|
||||
return;
|
||||
}
|
||||
|
||||
oxm = (struct ofp_ox_match *)bp;
|
||||
bp += sizeof(*oxm);
|
||||
length -= sizeof(*oxm);
|
||||
if (length < oxm->oxm_length) {
|
||||
printf(" [|OpenFlow]");
|
||||
return;
|
||||
}
|
||||
|
||||
ofp_print_oxm(oxm, bp, length);
|
||||
|
||||
bp += oxm->oxm_length;
|
||||
length -= oxm->oxm_length;
|
||||
omlen -= min(sizeof(*oxm) + oxm->oxm_length, omlen);
|
||||
if (omlen)
|
||||
goto parse_next_oxm;
|
||||
ofp_print_oxm_field(bp, length, omlen, 0);
|
||||
|
||||
print_packet:
|
||||
if (haspacket == 0)
|
||||
@ -322,7 +331,6 @@ void
|
||||
ofp_print_flowremoved(const u_char *bp, u_int length)
|
||||
{
|
||||
struct ofp_flow_removed *fr;
|
||||
struct ofp_ox_match *oxm;
|
||||
int omtype, omlen;
|
||||
|
||||
if (length < sizeof(*fr)) {
|
||||
@ -355,27 +363,7 @@ ofp_print_flowremoved(const u_char *bp, u_int length)
|
||||
bp += sizeof(*fr);
|
||||
length -= sizeof(*fr);
|
||||
|
||||
parse_next_oxm:
|
||||
if (length < sizeof(*oxm)) {
|
||||
printf(" [|OpenFlow]");
|
||||
return;
|
||||
}
|
||||
|
||||
oxm = (struct ofp_ox_match *)bp;
|
||||
bp += sizeof(*oxm);
|
||||
length -= sizeof(*oxm);
|
||||
if (length < oxm->oxm_length) {
|
||||
printf(" [|OpenFlow]");
|
||||
return;
|
||||
}
|
||||
|
||||
ofp_print_oxm(oxm, bp, length);
|
||||
|
||||
bp += oxm->oxm_length;
|
||||
length -= oxm->oxm_length;
|
||||
omlen -= min(sizeof(*oxm) + oxm->oxm_length, omlen);
|
||||
if (omlen)
|
||||
goto parse_next_oxm;
|
||||
ofp_print_oxm_field(bp, length, omlen, 0);
|
||||
}
|
||||
|
||||
void
|
||||
@ -453,7 +441,6 @@ void
|
||||
ofp_print_flowmod(const u_char *bp, u_int length)
|
||||
{
|
||||
struct ofp_flow_mod *fm;
|
||||
struct ofp_ox_match *oxm;
|
||||
struct ofp_instruction *i;
|
||||
int omtype, omlen, ilen;
|
||||
int instructionslen, padsize;
|
||||
@ -498,27 +485,10 @@ ofp_print_flowmod(const u_char *bp, u_int length)
|
||||
goto parse_next_instruction;
|
||||
}
|
||||
|
||||
parse_next_oxm:
|
||||
if (length < sizeof(*oxm)) {
|
||||
printf(" [|OpenFlow]");
|
||||
return;
|
||||
}
|
||||
ofp_print_oxm_field(bp, length, omlen, 0);
|
||||
|
||||
oxm = (struct ofp_ox_match *)bp;
|
||||
bp += sizeof(*oxm);
|
||||
length -= sizeof(*oxm);
|
||||
if (length < oxm->oxm_length) {
|
||||
printf(" [|OpenFlow]");
|
||||
return;
|
||||
}
|
||||
|
||||
ofp_print_oxm(oxm, bp, length);
|
||||
|
||||
bp += oxm->oxm_length;
|
||||
length -= oxm->oxm_length;
|
||||
omlen -= min(sizeof(*oxm) + oxm->oxm_length, omlen);
|
||||
if (omlen)
|
||||
goto parse_next_oxm;
|
||||
bp += omlen;
|
||||
length -= omlen;
|
||||
|
||||
/* Skip padding if any. */
|
||||
if (padsize) {
|
||||
@ -1017,7 +987,6 @@ void
|
||||
action_print_setfield(const u_char *bp, u_int length)
|
||||
{
|
||||
struct ofp_action_set_field *asf;
|
||||
struct ofp_ox_match *oxm;
|
||||
int omlen;
|
||||
|
||||
if (length < (sizeof(*asf) - AH_UNPADDED)) {
|
||||
@ -1030,27 +999,7 @@ action_print_setfield(const u_char *bp, u_int length)
|
||||
if (omlen == 0)
|
||||
return;
|
||||
|
||||
parse_next_oxm:
|
||||
if (length < sizeof(*oxm)) {
|
||||
printf(" [|OpenFlow]");
|
||||
return;
|
||||
}
|
||||
|
||||
oxm = (struct ofp_ox_match *)bp;
|
||||
bp += sizeof(*oxm);
|
||||
length -= sizeof(*oxm);
|
||||
if (length < oxm->oxm_length) {
|
||||
printf(" [|OpenFlow]");
|
||||
return;
|
||||
}
|
||||
|
||||
ofp_print_oxm(oxm, bp, length);
|
||||
|
||||
bp += oxm->oxm_length;
|
||||
length -= oxm->oxm_length;
|
||||
omlen -= min(sizeof(*oxm) + oxm->oxm_length, omlen);
|
||||
if (omlen)
|
||||
goto parse_next_oxm;
|
||||
ofp_print_oxm_field(bp, length, omlen, 1);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1094,6 +1043,7 @@ ofp_print_action(struct ofp_action_header *ah, const u_char *bp, u_int length)
|
||||
break;
|
||||
|
||||
case OFP_ACTION_SET_FIELD:
|
||||
action_print_setfield(bp, length);
|
||||
break;
|
||||
|
||||
case OFP_ACTION_COPY_TTL_OUT:
|
||||
|
Loading…
Reference in New Issue
Block a user