mirror of
https://github.com/openvswitch/ovs
synced 2025-08-22 18:07:40 +00:00
Support userdata in NXT_PACKET_IN2.
Signed-off-by: Ben Pfaff <blp@ovn.org> Acked-by: Jarno Rajahalme <jarno@ovn.org>
This commit is contained in:
parent
4adaf1828a
commit
bdcad671e0
3
NEWS
3
NEWS
@ -5,7 +5,8 @@ Post-v2.5.0
|
||||
- OpenFlow:
|
||||
* OpenFlow 1.1+ OFPT_QUEUE_GET_CONFIG_REQUEST now supports OFPP_ANY.
|
||||
* OpenFlow 1.4+ OFPMP_QUEUE_DESC is now supported.
|
||||
* New property-based packet-in message format NXT_PACKET_IN2.
|
||||
* New property-based packet-in message format NXT_PACKET_IN2 with support
|
||||
for arbitrary user-provided data.
|
||||
- ovs-ofctl:
|
||||
* queue-get-config command now allows a queue ID to be specified.
|
||||
- DPDK:
|
||||
|
@ -254,6 +254,7 @@ enum nx_packet_in2_prop_type {
|
||||
/* Other. */
|
||||
NXPINT_REASON, /* uint8_t, one of OFPR_*. */
|
||||
NXPINT_METADATA, /* NXM or OXM for metadata fields. */
|
||||
NXPINT_USERDATA, /* From NXAST_CONTROLLER2 userdata. */
|
||||
};
|
||||
|
||||
/* Configures the "role" of the sending controller. The default role is:
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "nx-match.h"
|
||||
#include "odp-netlink.h"
|
||||
#include "ofp-parse.h"
|
||||
#include "ofp-prop.h"
|
||||
#include "ofp-util.h"
|
||||
#include "ofpbuf.h"
|
||||
#include "unaligned.h"
|
||||
@ -273,6 +274,8 @@ enum ofp_raw_action_type {
|
||||
|
||||
/* NX1.0+(20): struct nx_action_controller. */
|
||||
NXAST_RAW_CONTROLLER,
|
||||
/* NX1.0+(37): struct nx_action_controller2, ... */
|
||||
NXAST_RAW_CONTROLLER2,
|
||||
|
||||
/* NX1.0+(22): struct nx_action_write_metadata. */
|
||||
NXAST_RAW_WRITE_METADATA,
|
||||
@ -625,6 +628,27 @@ struct nx_action_controller {
|
||||
};
|
||||
OFP_ASSERT(sizeof(struct nx_action_controller) == 16);
|
||||
|
||||
/* Properties for NXAST_CONTROLLER2. */
|
||||
enum nx_action_controller2_prop_type {
|
||||
NXAC2PT_MAX_LEN, /* ovs_be16 max bytes to send (default all). */
|
||||
NXAC2PT_CONTROLLER_ID, /* ovs_be16 dest controller ID (default 0). */
|
||||
NXAC2PT_REASON, /* uint8_t reason (OFPR_*), default 0. */
|
||||
NXAC2PT_USERDATA, /* Data to copy into NXPINT_USERDATA. */
|
||||
};
|
||||
|
||||
/* Action structure for NXAST_CONTROLLER2.
|
||||
*
|
||||
* This replacement for NXAST_CONTROLLER makes it extensible via properties. */
|
||||
struct nx_action_controller2 {
|
||||
ovs_be16 type; /* OFPAT_VENDOR. */
|
||||
ovs_be16 len; /* Length is 16 or more. */
|
||||
ovs_be32 vendor; /* NX_VENDOR_ID. */
|
||||
ovs_be16 subtype; /* NXAST_CONTROLLER2. */
|
||||
uint8_t zeros[6]; /* Must be zero. */
|
||||
/* Followed by NXAC2PT_* properties. */
|
||||
};
|
||||
OFP_ASSERT(sizeof(struct nx_action_controller2) == 16);
|
||||
|
||||
static enum ofperr
|
||||
decode_NXAST_RAW_CONTROLLER(const struct nx_action_controller *nac,
|
||||
enum ofp_version ofp_version OVS_UNUSED,
|
||||
@ -633,9 +657,77 @@ decode_NXAST_RAW_CONTROLLER(const struct nx_action_controller *nac,
|
||||
struct ofpact_controller *oc;
|
||||
|
||||
oc = ofpact_put_CONTROLLER(out);
|
||||
oc->ofpact.raw = NXAST_RAW_CONTROLLER;
|
||||
oc->max_len = ntohs(nac->max_len);
|
||||
oc->controller_id = ntohs(nac->controller_id);
|
||||
oc->reason = nac->reason;
|
||||
ofpact_finish(out, &oc->ofpact);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum ofperr
|
||||
decode_NXAST_RAW_CONTROLLER2(const struct nx_action_controller2 *nac2,
|
||||
enum ofp_version ofp_version OVS_UNUSED,
|
||||
struct ofpbuf *out)
|
||||
{
|
||||
if (!is_all_zeros(nac2->zeros, sizeof nac2->zeros)) {
|
||||
return OFPERR_NXBRC_MUST_BE_ZERO;
|
||||
}
|
||||
|
||||
size_t start_ofs = out->size;
|
||||
struct ofpact_controller *oc = ofpact_put_CONTROLLER(out);
|
||||
oc->ofpact.raw = NXAST_RAW_CONTROLLER2;
|
||||
oc->max_len = UINT16_MAX;
|
||||
oc->reason = OFPR_ACTION;
|
||||
|
||||
struct ofpbuf properties;
|
||||
ofpbuf_use_const(&properties, nac2, ntohs(nac2->len));
|
||||
ofpbuf_pull(&properties, sizeof *nac2);
|
||||
|
||||
while (properties.size > 0) {
|
||||
struct ofpbuf payload;
|
||||
uint64_t type;
|
||||
|
||||
enum ofperr error = ofpprop_pull(&properties, &payload, &type);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case NXAC2PT_MAX_LEN:
|
||||
error = ofpprop_parse_u16(&payload, &oc->max_len);
|
||||
break;
|
||||
|
||||
case NXAC2PT_CONTROLLER_ID:
|
||||
error = ofpprop_parse_u16(&payload, &oc->controller_id);
|
||||
break;
|
||||
|
||||
case NXAC2PT_REASON: {
|
||||
uint8_t u8;
|
||||
error = ofpprop_parse_u8(&payload, &u8);
|
||||
oc->reason = u8;
|
||||
break;
|
||||
}
|
||||
|
||||
case NXAC2PT_USERDATA:
|
||||
out->size = start_ofs + OFPACT_CONTROLLER_SIZE;
|
||||
ofpbuf_put(out, payload.msg, ofpbuf_msgsize(&payload));
|
||||
oc = ofpbuf_at_assert(out, start_ofs, sizeof *oc);
|
||||
oc->userdata_len = ofpbuf_msgsize(&payload);
|
||||
break;
|
||||
|
||||
default:
|
||||
error = OFPPROP_UNKNOWN(false, "NXAST_RAW_CONTROLLER2", type);
|
||||
break;
|
||||
}
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
ofpact_finish(out, &oc->ofpact);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -644,6 +736,26 @@ encode_CONTROLLER(const struct ofpact_controller *controller,
|
||||
enum ofp_version ofp_version OVS_UNUSED,
|
||||
struct ofpbuf *out)
|
||||
{
|
||||
if (controller->userdata_len
|
||||
|| controller->ofpact.raw == NXAST_RAW_CONTROLLER2) {
|
||||
size_t start_ofs = out->size;
|
||||
put_NXAST_CONTROLLER2(out);
|
||||
if (controller->max_len != UINT16_MAX) {
|
||||
ofpprop_put_u16(out, NXAC2PT_MAX_LEN, controller->max_len);
|
||||
}
|
||||
if (controller->controller_id != 0) {
|
||||
ofpprop_put_u16(out, NXAC2PT_CONTROLLER_ID,
|
||||
controller->controller_id);
|
||||
}
|
||||
if (controller->reason != OFPR_ACTION) {
|
||||
ofpprop_put_u8(out, NXAC2PT_REASON, controller->reason);
|
||||
}
|
||||
if (controller->userdata_len != 0) {
|
||||
ofpprop_put(out, NXAC2PT_USERDATA, controller->userdata,
|
||||
controller->userdata_len);
|
||||
}
|
||||
pad_ofpat(out, start_ofs);
|
||||
} else {
|
||||
struct nx_action_controller *nac;
|
||||
|
||||
nac = put_NXAST_CONTROLLER(out);
|
||||
@ -651,6 +763,7 @@ encode_CONTROLLER(const struct ofpact_controller *controller,
|
||||
nac->controller_id = htons(controller->controller_id);
|
||||
nac->reason = controller->reason;
|
||||
}
|
||||
}
|
||||
|
||||
static char * OVS_WARN_UNUSED_RESULT
|
||||
parse_CONTROLLER(char *arg, struct ofpbuf *ofpacts,
|
||||
@ -659,6 +772,7 @@ parse_CONTROLLER(char *arg, struct ofpbuf *ofpacts,
|
||||
enum ofp_packet_in_reason reason = OFPR_ACTION;
|
||||
uint16_t controller_id = 0;
|
||||
uint16_t max_len = UINT16_MAX;
|
||||
const char *userdata = NULL;
|
||||
|
||||
if (!arg[0]) {
|
||||
/* Use defaults. */
|
||||
@ -685,6 +799,8 @@ parse_CONTROLLER(char *arg, struct ofpbuf *ofpacts,
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
} else if (!strcmp(name, "userdata")) {
|
||||
userdata = value;
|
||||
} else {
|
||||
return xasprintf("unknown key \"%s\" parsing controller "
|
||||
"action", name);
|
||||
@ -692,7 +808,7 @@ parse_CONTROLLER(char *arg, struct ofpbuf *ofpacts,
|
||||
}
|
||||
}
|
||||
|
||||
if (reason == OFPR_ACTION && controller_id == 0) {
|
||||
if (reason == OFPR_ACTION && controller_id == 0 && !userdata) {
|
||||
struct ofpact_output *output;
|
||||
|
||||
output = ofpact_put_OUTPUT(ofpacts);
|
||||
@ -705,15 +821,39 @@ parse_CONTROLLER(char *arg, struct ofpbuf *ofpacts,
|
||||
controller->max_len = max_len;
|
||||
controller->reason = reason;
|
||||
controller->controller_id = controller_id;
|
||||
|
||||
if (userdata) {
|
||||
size_t start_ofs = ofpacts->size;
|
||||
const char *end = ofpbuf_put_hex(ofpacts, userdata, NULL);
|
||||
if (*end) {
|
||||
return xstrdup("bad hex digit in `controller' "
|
||||
"action `userdata'");
|
||||
}
|
||||
size_t userdata_len = ofpacts->size - start_ofs;
|
||||
controller = ofpacts->header;
|
||||
controller->userdata_len = userdata_len;
|
||||
}
|
||||
ofpact_finish(ofpacts, &controller->ofpact);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
format_hex_arg(struct ds *s, const uint8_t *data, size_t len)
|
||||
{
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (i) {
|
||||
ds_put_char(s, '.');
|
||||
}
|
||||
ds_put_format(s, "%02"PRIx8, data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
format_CONTROLLER(const struct ofpact_controller *a, struct ds *s)
|
||||
{
|
||||
if (a->reason == OFPR_ACTION && a->controller_id == 0) {
|
||||
if (a->reason == OFPR_ACTION && !a->controller_id && !a->userdata_len) {
|
||||
ds_put_format(s, "CONTROLLER:%"PRIu16, a->max_len);
|
||||
} else {
|
||||
enum ofp_packet_in_reason reason = a->reason;
|
||||
@ -732,6 +872,11 @@ format_CONTROLLER(const struct ofpact_controller *a, struct ds *s)
|
||||
if (a->controller_id != 0) {
|
||||
ds_put_format(s, "id=%"PRIu16",", a->controller_id);
|
||||
}
|
||||
if (a->userdata_len) {
|
||||
ds_put_cstr(s, "userdata=");
|
||||
format_hex_arg(s, a->userdata, a->userdata_len);
|
||||
ds_put_char(s, ',');
|
||||
}
|
||||
ds_chomp(s, ',');
|
||||
ds_put_char(s, ')');
|
||||
}
|
||||
@ -4400,15 +4545,8 @@ parse_NOTE(const char *arg, struct ofpbuf *ofpacts,
|
||||
static void
|
||||
format_NOTE(const struct ofpact_note *a, struct ds *s)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
ds_put_cstr(s, "note:");
|
||||
for (i = 0; i < a->length; i++) {
|
||||
if (i) {
|
||||
ds_put_char(s, '.');
|
||||
}
|
||||
ds_put_format(s, "%02"PRIx8, a->data[i]);
|
||||
}
|
||||
format_hex_arg(s, a->data, a->length);
|
||||
}
|
||||
|
||||
/* Exit action. */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2013, 2014, 2015 Nicira, Inc.
|
||||
* Copyright (c) 2012, 2013, 2014, 2015, 2016 Nicira, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -56,7 +56,7 @@
|
||||
/* Output. */ \
|
||||
OFPACT(OUTPUT, ofpact_output, ofpact, "output") \
|
||||
OFPACT(GROUP, ofpact_group, ofpact, "group") \
|
||||
OFPACT(CONTROLLER, ofpact_controller, ofpact, "controller") \
|
||||
OFPACT(CONTROLLER, ofpact_controller, userdata, "controller") \
|
||||
OFPACT(ENQUEUE, ofpact_enqueue, ofpact, "enqueue") \
|
||||
OFPACT(OUTPUT_REG, ofpact_output_reg, ofpact, "output_reg") \
|
||||
OFPACT(BUNDLE, ofpact_bundle, slaves, "bundle") \
|
||||
@ -245,6 +245,11 @@ struct ofpact_controller {
|
||||
uint16_t max_len; /* Maximum length to send to controller. */
|
||||
uint16_t controller_id; /* Controller ID to send packet-in. */
|
||||
enum ofp_packet_in_reason reason; /* Reason to put in packet-in. */
|
||||
|
||||
/* Arbitrary data to include in the packet-in message (currently, only in
|
||||
* NXT_PACKET_IN2). */
|
||||
uint16_t userdata_len;
|
||||
uint8_t userdata[];
|
||||
};
|
||||
|
||||
/* OFPACT_ENQUEUE.
|
||||
|
@ -94,6 +94,17 @@ ofp_packet_to_string(const void *data, size_t len)
|
||||
return ds_cstr(&ds);
|
||||
}
|
||||
|
||||
static void
|
||||
format_hex_arg(struct ds *s, const uint8_t *data, size_t len)
|
||||
{
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (i) {
|
||||
ds_put_char(s, '.');
|
||||
}
|
||||
ds_put_format(s, "%02"PRIx8, data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ofp_print_packet_in(struct ds *string, const struct ofp_header *oh,
|
||||
int verbosity)
|
||||
@ -141,6 +152,12 @@ ofp_print_packet_in(struct ds *string, const struct ofp_header *oh,
|
||||
}
|
||||
ds_put_char(string, '\n');
|
||||
|
||||
if (pin.userdata_len) {
|
||||
ds_put_cstr(string, " userdata=");
|
||||
format_hex_arg(string, pin.userdata, pin.userdata_len);
|
||||
ds_put_char(string, '\n');
|
||||
}
|
||||
|
||||
if (verbosity > 0) {
|
||||
char *packet = ofp_packet_to_string(pin.packet, pin.packet_len);
|
||||
ds_put_cstr(string, packet);
|
||||
|
@ -3361,6 +3361,11 @@ decode_nx_packet_in2(const struct ofp_header *oh,
|
||||
&pin->flow_metadata);
|
||||
break;
|
||||
|
||||
case NXPINT_USERDATA:
|
||||
pin->userdata = payload.msg;
|
||||
pin->userdata_len = ofpbuf_msgsize(&payload);
|
||||
break;
|
||||
|
||||
default:
|
||||
error = OFPPROP_UNKNOWN(true, "NX_PACKET_IN2", type);
|
||||
break;
|
||||
@ -3596,6 +3601,10 @@ ofputil_encode_nx_packet_in2(const struct ofputil_packet_in *pin,
|
||||
oxm_put_raw(msg, &pin->flow_metadata, version);
|
||||
ofpprop_end(msg, start);
|
||||
|
||||
if (pin->userdata_len) {
|
||||
ofpprop_put(msg, NXPINT_USERDATA, pin->userdata, pin->userdata_len);
|
||||
}
|
||||
|
||||
ofpmsg_update_length(msg);
|
||||
return msg;
|
||||
}
|
||||
|
@ -441,6 +441,10 @@ struct ofputil_packet_in {
|
||||
* that case, 'cookie' is UINT64_MAX. */
|
||||
uint8_t table_id; /* OpenFlow table ID. */
|
||||
ovs_be64 cookie; /* Flow's cookie. */
|
||||
|
||||
/* Arbitrary user-provided data. */
|
||||
uint8_t *userdata;
|
||||
size_t userdata_len;
|
||||
};
|
||||
|
||||
struct ofpbuf *ofputil_encode_packet_in(const struct ofputil_packet_in *,
|
||||
|
@ -2248,5 +2248,6 @@ void
|
||||
ofproto_async_msg_free(struct ofproto_async_msg *am)
|
||||
{
|
||||
free(am->pin.up.packet);
|
||||
free(am->pin.up.userdata);
|
||||
free(am);
|
||||
}
|
||||
|
@ -3602,7 +3602,8 @@ flood_packets(struct xlate_ctx *ctx, bool all)
|
||||
static void
|
||||
execute_controller_action(struct xlate_ctx *ctx, int len,
|
||||
enum ofp_packet_in_reason reason,
|
||||
uint16_t controller_id)
|
||||
uint16_t controller_id,
|
||||
const uint8_t *userdata, size_t userdata_len)
|
||||
{
|
||||
struct dp_packet *packet;
|
||||
|
||||
@ -3638,6 +3639,10 @@ execute_controller_action(struct xlate_ctx *ctx, int len,
|
||||
.reason = reason,
|
||||
.table_id = ctx->table_id,
|
||||
.cookie = ctx->rule_cookie,
|
||||
.userdata = (userdata_len
|
||||
? xmemdup(userdata, userdata_len)
|
||||
: NULL),
|
||||
.userdata_len = userdata_len,
|
||||
},
|
||||
.max_len = len,
|
||||
},
|
||||
@ -3775,7 +3780,7 @@ compose_dec_ttl(struct xlate_ctx *ctx, struct ofpact_cnt_ids *ids)
|
||||
|
||||
for (i = 0; i < ids->n_controllers; i++) {
|
||||
execute_controller_action(ctx, UINT16_MAX, OFPR_INVALID_TTL,
|
||||
ids->cnt_ids[i]);
|
||||
ids->cnt_ids[i], NULL, 0);
|
||||
}
|
||||
|
||||
/* Stop processing for current table. */
|
||||
@ -3824,7 +3829,8 @@ compose_dec_mpls_ttl_action(struct xlate_ctx *ctx)
|
||||
set_mpls_lse_ttl(&flow->mpls_lse[0], ttl);
|
||||
return false;
|
||||
} else {
|
||||
execute_controller_action(ctx, UINT16_MAX, OFPR_INVALID_TTL, 0);
|
||||
execute_controller_action(ctx, UINT16_MAX, OFPR_INVALID_TTL, 0,
|
||||
NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3862,7 +3868,7 @@ xlate_output_action(struct xlate_ctx *ctx,
|
||||
(ctx->in_group ? OFPR_GROUP
|
||||
: ctx->in_action_set ? OFPR_ACTION_SET
|
||||
: OFPR_ACTION),
|
||||
0);
|
||||
0, NULL, 0);
|
||||
break;
|
||||
case OFPP_NONE:
|
||||
break;
|
||||
@ -4473,7 +4479,9 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
|
||||
controller = ofpact_get_CONTROLLER(a);
|
||||
execute_controller_action(ctx, controller->max_len,
|
||||
controller->reason,
|
||||
controller->controller_id);
|
||||
controller->controller_id,
|
||||
controller->userdata,
|
||||
controller->userdata_len);
|
||||
break;
|
||||
|
||||
case OFPACT_ENQUEUE:
|
||||
|
@ -1411,6 +1411,7 @@ add_internal_flows(struct ofproto_dpif *ofproto)
|
||||
controller->max_len = UINT16_MAX;
|
||||
controller->controller_id = 0;
|
||||
controller->reason = OFPR_IMPLICIT_MISS;
|
||||
ofpact_finish(&ofpacts, &controller->ofpact);
|
||||
|
||||
error = add_internal_miss_flow(ofproto, id++, &ofpacts,
|
||||
&ofproto->miss_rule);
|
||||
|
@ -113,6 +113,13 @@ ffff 0010 00002320 0013 000a 0014 0000
|
||||
# actions=controller(reason=invalid_ttl,max_len=1234,id=5678)
|
||||
ffff 0010 00002320 0014 04d2 162e 02 00
|
||||
|
||||
# actions=controller(reason=invalid_ttl,max_len=1234,id=5678,userdata=01.02.03.04.05)
|
||||
ffff 0038 00002320 0025 000000000000 dnl
|
||||
0000 0008 04d2 0000 dnl
|
||||
0001 0008 162e 0000 dnl
|
||||
0002 0005 02 000000 dnl
|
||||
0003 0009 0102030405 00000000000000
|
||||
|
||||
# actions=dec_ttl(32768,12345,90,765,1024)
|
||||
ffff 0020 00002320 0015 000500000000 80003039005A02fd 0400000000000000
|
||||
|
||||
|
@ -2849,7 +2849,7 @@ AT_CLEANUP
|
||||
AT_SETUP([NX_PACKET_IN2])
|
||||
AT_KEYWORDS([ofp-print])
|
||||
AT_CHECK([ovs-ofctl ofp-print "
|
||||
01 04 0088 00000000 00002320 0000001e
|
||||
01 04 0098 00000000 00002320 0000001e
|
||||
0000 0034
|
||||
82 82 82 82 82 82 80 81 81 81 81 81 81 00 00 50
|
||||
08 00 45 00 00 28 00 00 00 00 00 06 32 05 53 53
|
||||
@ -2859,9 +2859,12 @@ AT_CHECK([ovs-ofctl ofp-print "
|
||||
0003 0005 07 000000
|
||||
0004 0010 00000000 fedcba9876543210
|
||||
0005 0005 01 000000
|
||||
0006 0010 80000408 5a5a5a5a5a5a5a5a"
|
||||
0006 0010 80000408 5a5a5a5a5a5a5a5a
|
||||
0007 0009 0102030405 00000000000000
|
||||
"
|
||||
], [0], [dnl
|
||||
NXT_PACKET_IN2 (xid=0x0): table_id=7 cookie=0xfedcba9876543210 total_len=64 metadata=0x5a5a5a5a5a5a5a5a (via action) data_len=48 buffer=0x00000114
|
||||
userdata=01.02.03.04.05
|
||||
ip,dl_vlan=80,dl_vlan_pcp=0,dl_src=80:81:81:81:81:81,dl_dst=82:82:82:82:82:82,nw_src=0.0.0.0,nw_dst=0.0.0.0,nw_proto=0,nw_tos=0,nw_ecn=0,nw_ttl=0
|
||||
])
|
||||
AT_CLEANUP
|
||||
|
@ -3353,8 +3353,8 @@ OFPT_BARRIER_REPLY (OF1.1):
|
||||
OVS_VSWITCHD_STOP
|
||||
AT_CLEANUP
|
||||
|
||||
dnl This test checks that metadata is encoded in NXT_PACKET_IN2.
|
||||
AT_SETUP([ofproto - packet-out with metadata (NXT_PACKET_IN2)])
|
||||
dnl This test checks that metadata and userdata are encoded in NXT_PACKET_IN2.
|
||||
AT_SETUP([ofproto - packet-out with metadata and userdata (NXT_PACKET_IN2)])
|
||||
OVS_VSWITCHD_START
|
||||
|
||||
# Start a monitor listening for packet-ins.
|
||||
@ -3365,7 +3365,7 @@ ovs-appctl -t ovs-ofctl ofctl/set-output-file monitor.log
|
||||
AT_CAPTURE_FILE([monitor.log])
|
||||
|
||||
# Send a packet-out with a load action to set some metadata, and forward to controller
|
||||
AT_CHECK([ovs-ofctl packet-out br0 controller 'load(0xfafafafa5a5a5a5a->OXM_OF_METADATA[[0..63]]), load(0xaa->NXM_NX_PKT_MARK[[]]), controller' '0001020304050010203040501234'])
|
||||
AT_CHECK([ovs-ofctl packet-out br0 controller 'load(0xfafafafa5a5a5a5a->OXM_OF_METADATA[[0..63]]), load(0xaa->NXM_NX_PKT_MARK[[]]), controller(userdata=01.02.03.04.05)' '0001020304050010203040501234'])
|
||||
|
||||
# Stop the monitor and check its output.
|
||||
ovs-appctl -t ovs-ofctl ofctl/barrier
|
||||
@ -3373,6 +3373,7 @@ ovs-appctl -t ovs-ofctl exit
|
||||
|
||||
AT_CHECK([sed 's/ (xid=0x[[0-9a-fA-F]]*)//' monitor.log], [0], [dnl
|
||||
NXT_PACKET_IN2: total_len=14 pkt_mark=0xaa,metadata=0xfafafafa5a5a5a5a,in_port=CONTROLLER (via action) data_len=14 (unbuffered)
|
||||
userdata=01.02.03.04.05
|
||||
vlan_tci=0x0000,dl_src=00:10:20:30:40:50,dl_dst=00:01:02:03:04:05,dl_type=0x1234
|
||||
OFPT_BARRIER_REPLY:
|
||||
])
|
||||
|
@ -1523,12 +1523,18 @@ default connection ID for each controller connection, and a given
|
||||
controller connection will only have a nonzero connection ID if its
|
||||
controller uses the \fBNXT_SET_CONTROLLER_ID\fR Nicira extension to
|
||||
OpenFlow.
|
||||
.IP "\fBuserdata=\fIhh\fR...\fR"
|
||||
Supplies the bytes represented as hex digits \fIhh\fR as additional
|
||||
data to the controller in the packet-in message. Pairs of hex digits
|
||||
may be separated by periods for readability.
|
||||
.
|
||||
.RE
|
||||
.IP
|
||||
Any \fIreason\fR other than \fBaction\fR and any nonzero
|
||||
\fIcontroller-id\fR uses a Nicira vendor extension that, as of this
|
||||
writing, is only known to be implemented by Open vSwitch (version 1.6
|
||||
or later).
|
||||
If any \fIreason\fR other than \fBaction\fR or any nonzero
|
||||
\fIcontroller-id\fR is supplied, Open vSwitch extension
|
||||
\fBNXAST_CONTROLLER\fR, supported by Open vSwitch 1.6 and later, is
|
||||
used. If \fBuserdata\fR is supplied, then \fBNXAST_CONTROLLER2\fR,
|
||||
supported by Open vSwitch 2.6 and later, is used.
|
||||
.
|
||||
.IP \fBcontroller\fR
|
||||
.IQ \fBcontroller\fR[\fB:\fInbytes\fR]
|
||||
@ -2868,8 +2874,10 @@ little reason to use it with those versions of OpenFlow).
|
||||
.
|
||||
.IP "\fBnxt_packet_in2\fR"
|
||||
This uses the \fBNXT_PACKET_IN2\fR message, which is extensible and
|
||||
should avoid the need to define new formats later. Open vSwitch 2.6
|
||||
and later support this format.
|
||||
should avoid the need to define new formats later. In particular,
|
||||
this format supports passing arbitrary user-provided data to a
|
||||
controller using the \fBuserdata\fB option on the \fBcontroller\fR
|
||||
action. Open vSwitch 2.6 and later support this format.
|
||||
.
|
||||
.RE
|
||||
.IP
|
||||
|
Loading…
x
Reference in New Issue
Block a user