2
0
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:
Ben Pfaff 2016-02-19 15:53:26 -08:00
parent 4adaf1828a
commit bdcad671e0
14 changed files with 238 additions and 34 deletions

3
NEWS
View File

@ -5,7 +5,8 @@ Post-v2.5.0
- OpenFlow: - OpenFlow:
* OpenFlow 1.1+ OFPT_QUEUE_GET_CONFIG_REQUEST now supports OFPP_ANY. * OpenFlow 1.1+ OFPT_QUEUE_GET_CONFIG_REQUEST now supports OFPP_ANY.
* OpenFlow 1.4+ OFPMP_QUEUE_DESC is now supported. * 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: - ovs-ofctl:
* queue-get-config command now allows a queue ID to be specified. * queue-get-config command now allows a queue ID to be specified.
- DPDK: - DPDK:

View File

@ -254,6 +254,7 @@ enum nx_packet_in2_prop_type {
/* Other. */ /* Other. */
NXPINT_REASON, /* uint8_t, one of OFPR_*. */ NXPINT_REASON, /* uint8_t, one of OFPR_*. */
NXPINT_METADATA, /* NXM or OXM for metadata fields. */ 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: /* Configures the "role" of the sending controller. The default role is:

View File

@ -30,6 +30,7 @@
#include "nx-match.h" #include "nx-match.h"
#include "odp-netlink.h" #include "odp-netlink.h"
#include "ofp-parse.h" #include "ofp-parse.h"
#include "ofp-prop.h"
#include "ofp-util.h" #include "ofp-util.h"
#include "ofpbuf.h" #include "ofpbuf.h"
#include "unaligned.h" #include "unaligned.h"
@ -273,6 +274,8 @@ enum ofp_raw_action_type {
/* NX1.0+(20): struct nx_action_controller. */ /* NX1.0+(20): struct nx_action_controller. */
NXAST_RAW_CONTROLLER, NXAST_RAW_CONTROLLER,
/* NX1.0+(37): struct nx_action_controller2, ... */
NXAST_RAW_CONTROLLER2,
/* NX1.0+(22): struct nx_action_write_metadata. */ /* NX1.0+(22): struct nx_action_write_metadata. */
NXAST_RAW_WRITE_METADATA, NXAST_RAW_WRITE_METADATA,
@ -625,6 +628,27 @@ struct nx_action_controller {
}; };
OFP_ASSERT(sizeof(struct nx_action_controller) == 16); 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 static enum ofperr
decode_NXAST_RAW_CONTROLLER(const struct nx_action_controller *nac, decode_NXAST_RAW_CONTROLLER(const struct nx_action_controller *nac,
enum ofp_version ofp_version OVS_UNUSED, 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; struct ofpact_controller *oc;
oc = ofpact_put_CONTROLLER(out); oc = ofpact_put_CONTROLLER(out);
oc->ofpact.raw = NXAST_RAW_CONTROLLER;
oc->max_len = ntohs(nac->max_len); oc->max_len = ntohs(nac->max_len);
oc->controller_id = ntohs(nac->controller_id); oc->controller_id = ntohs(nac->controller_id);
oc->reason = nac->reason; 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; return 0;
} }
@ -644,6 +736,26 @@ encode_CONTROLLER(const struct ofpact_controller *controller,
enum ofp_version ofp_version OVS_UNUSED, enum ofp_version ofp_version OVS_UNUSED,
struct ofpbuf *out) 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; struct nx_action_controller *nac;
nac = put_NXAST_CONTROLLER(out); nac = put_NXAST_CONTROLLER(out);
@ -651,6 +763,7 @@ encode_CONTROLLER(const struct ofpact_controller *controller,
nac->controller_id = htons(controller->controller_id); nac->controller_id = htons(controller->controller_id);
nac->reason = controller->reason; nac->reason = controller->reason;
} }
}
static char * OVS_WARN_UNUSED_RESULT static char * OVS_WARN_UNUSED_RESULT
parse_CONTROLLER(char *arg, struct ofpbuf *ofpacts, 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; enum ofp_packet_in_reason reason = OFPR_ACTION;
uint16_t controller_id = 0; uint16_t controller_id = 0;
uint16_t max_len = UINT16_MAX; uint16_t max_len = UINT16_MAX;
const char *userdata = NULL;
if (!arg[0]) { if (!arg[0]) {
/* Use defaults. */ /* Use defaults. */
@ -685,6 +799,8 @@ parse_CONTROLLER(char *arg, struct ofpbuf *ofpacts,
if (error) { if (error) {
return error; return error;
} }
} else if (!strcmp(name, "userdata")) {
userdata = value;
} else { } else {
return xasprintf("unknown key \"%s\" parsing controller " return xasprintf("unknown key \"%s\" parsing controller "
"action", name); "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; struct ofpact_output *output;
output = ofpact_put_OUTPUT(ofpacts); output = ofpact_put_OUTPUT(ofpacts);
@ -705,15 +821,39 @@ parse_CONTROLLER(char *arg, struct ofpbuf *ofpacts,
controller->max_len = max_len; controller->max_len = max_len;
controller->reason = reason; controller->reason = reason;
controller->controller_id = controller_id; 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; 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 static void
format_CONTROLLER(const struct ofpact_controller *a, struct ds *s) 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); ds_put_format(s, "CONTROLLER:%"PRIu16, a->max_len);
} else { } else {
enum ofp_packet_in_reason reason = a->reason; 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) { if (a->controller_id != 0) {
ds_put_format(s, "id=%"PRIu16",", a->controller_id); 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_chomp(s, ',');
ds_put_char(s, ')'); ds_put_char(s, ')');
} }
@ -4400,15 +4545,8 @@ parse_NOTE(const char *arg, struct ofpbuf *ofpacts,
static void static void
format_NOTE(const struct ofpact_note *a, struct ds *s) format_NOTE(const struct ofpact_note *a, struct ds *s)
{ {
size_t i;
ds_put_cstr(s, "note:"); ds_put_cstr(s, "note:");
for (i = 0; i < a->length; i++) { format_hex_arg(s, a->data, a->length);
if (i) {
ds_put_char(s, '.');
}
ds_put_format(s, "%02"PRIx8, a->data[i]);
}
} }
/* Exit action. */ /* Exit action. */

View File

@ -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"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -56,7 +56,7 @@
/* Output. */ \ /* Output. */ \
OFPACT(OUTPUT, ofpact_output, ofpact, "output") \ OFPACT(OUTPUT, ofpact_output, ofpact, "output") \
OFPACT(GROUP, ofpact_group, ofpact, "group") \ 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(ENQUEUE, ofpact_enqueue, ofpact, "enqueue") \
OFPACT(OUTPUT_REG, ofpact_output_reg, ofpact, "output_reg") \ OFPACT(OUTPUT_REG, ofpact_output_reg, ofpact, "output_reg") \
OFPACT(BUNDLE, ofpact_bundle, slaves, "bundle") \ 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 max_len; /* Maximum length to send to controller. */
uint16_t controller_id; /* Controller ID to send packet-in. */ uint16_t controller_id; /* Controller ID to send packet-in. */
enum ofp_packet_in_reason reason; /* Reason to put in 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. /* OFPACT_ENQUEUE.

View File

@ -94,6 +94,17 @@ ofp_packet_to_string(const void *data, size_t len)
return ds_cstr(&ds); 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 static void
ofp_print_packet_in(struct ds *string, const struct ofp_header *oh, ofp_print_packet_in(struct ds *string, const struct ofp_header *oh,
int verbosity) int verbosity)
@ -141,6 +152,12 @@ ofp_print_packet_in(struct ds *string, const struct ofp_header *oh,
} }
ds_put_char(string, '\n'); 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) { if (verbosity > 0) {
char *packet = ofp_packet_to_string(pin.packet, pin.packet_len); char *packet = ofp_packet_to_string(pin.packet, pin.packet_len);
ds_put_cstr(string, packet); ds_put_cstr(string, packet);

View File

@ -3361,6 +3361,11 @@ decode_nx_packet_in2(const struct ofp_header *oh,
&pin->flow_metadata); &pin->flow_metadata);
break; break;
case NXPINT_USERDATA:
pin->userdata = payload.msg;
pin->userdata_len = ofpbuf_msgsize(&payload);
break;
default: default:
error = OFPPROP_UNKNOWN(true, "NX_PACKET_IN2", type); error = OFPPROP_UNKNOWN(true, "NX_PACKET_IN2", type);
break; break;
@ -3596,6 +3601,10 @@ ofputil_encode_nx_packet_in2(const struct ofputil_packet_in *pin,
oxm_put_raw(msg, &pin->flow_metadata, version); oxm_put_raw(msg, &pin->flow_metadata, version);
ofpprop_end(msg, start); ofpprop_end(msg, start);
if (pin->userdata_len) {
ofpprop_put(msg, NXPINT_USERDATA, pin->userdata, pin->userdata_len);
}
ofpmsg_update_length(msg); ofpmsg_update_length(msg);
return msg; return msg;
} }

View File

@ -441,6 +441,10 @@ struct ofputil_packet_in {
* that case, 'cookie' is UINT64_MAX. */ * that case, 'cookie' is UINT64_MAX. */
uint8_t table_id; /* OpenFlow table ID. */ uint8_t table_id; /* OpenFlow table ID. */
ovs_be64 cookie; /* Flow's cookie. */ 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 *, struct ofpbuf *ofputil_encode_packet_in(const struct ofputil_packet_in *,

View File

@ -2248,5 +2248,6 @@ void
ofproto_async_msg_free(struct ofproto_async_msg *am) ofproto_async_msg_free(struct ofproto_async_msg *am)
{ {
free(am->pin.up.packet); free(am->pin.up.packet);
free(am->pin.up.userdata);
free(am); free(am);
} }

View File

@ -3602,7 +3602,8 @@ flood_packets(struct xlate_ctx *ctx, bool all)
static void static void
execute_controller_action(struct xlate_ctx *ctx, int len, execute_controller_action(struct xlate_ctx *ctx, int len,
enum ofp_packet_in_reason reason, 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; struct dp_packet *packet;
@ -3638,6 +3639,10 @@ execute_controller_action(struct xlate_ctx *ctx, int len,
.reason = reason, .reason = reason,
.table_id = ctx->table_id, .table_id = ctx->table_id,
.cookie = ctx->rule_cookie, .cookie = ctx->rule_cookie,
.userdata = (userdata_len
? xmemdup(userdata, userdata_len)
: NULL),
.userdata_len = userdata_len,
}, },
.max_len = 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++) { for (i = 0; i < ids->n_controllers; i++) {
execute_controller_action(ctx, UINT16_MAX, OFPR_INVALID_TTL, execute_controller_action(ctx, UINT16_MAX, OFPR_INVALID_TTL,
ids->cnt_ids[i]); ids->cnt_ids[i], NULL, 0);
} }
/* Stop processing for current table. */ /* 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); set_mpls_lse_ttl(&flow->mpls_lse[0], ttl);
return false; return false;
} else { } 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_group ? OFPR_GROUP
: ctx->in_action_set ? OFPR_ACTION_SET : ctx->in_action_set ? OFPR_ACTION_SET
: OFPR_ACTION), : OFPR_ACTION),
0); 0, NULL, 0);
break; break;
case OFPP_NONE: case OFPP_NONE:
break; break;
@ -4473,7 +4479,9 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
controller = ofpact_get_CONTROLLER(a); controller = ofpact_get_CONTROLLER(a);
execute_controller_action(ctx, controller->max_len, execute_controller_action(ctx, controller->max_len,
controller->reason, controller->reason,
controller->controller_id); controller->controller_id,
controller->userdata,
controller->userdata_len);
break; break;
case OFPACT_ENQUEUE: case OFPACT_ENQUEUE:

View File

@ -1411,6 +1411,7 @@ add_internal_flows(struct ofproto_dpif *ofproto)
controller->max_len = UINT16_MAX; controller->max_len = UINT16_MAX;
controller->controller_id = 0; controller->controller_id = 0;
controller->reason = OFPR_IMPLICIT_MISS; controller->reason = OFPR_IMPLICIT_MISS;
ofpact_finish(&ofpacts, &controller->ofpact);
error = add_internal_miss_flow(ofproto, id++, &ofpacts, error = add_internal_miss_flow(ofproto, id++, &ofpacts,
&ofproto->miss_rule); &ofproto->miss_rule);

View File

@ -113,6 +113,13 @@ ffff 0010 00002320 0013 000a 0014 0000
# actions=controller(reason=invalid_ttl,max_len=1234,id=5678) # actions=controller(reason=invalid_ttl,max_len=1234,id=5678)
ffff 0010 00002320 0014 04d2 162e 02 00 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) # actions=dec_ttl(32768,12345,90,765,1024)
ffff 0020 00002320 0015 000500000000 80003039005A02fd 0400000000000000 ffff 0020 00002320 0015 000500000000 80003039005A02fd 0400000000000000

View File

@ -2849,7 +2849,7 @@ AT_CLEANUP
AT_SETUP([NX_PACKET_IN2]) AT_SETUP([NX_PACKET_IN2])
AT_KEYWORDS([ofp-print]) AT_KEYWORDS([ofp-print])
AT_CHECK([ovs-ofctl ofp-print " AT_CHECK([ovs-ofctl ofp-print "
01 04 0088 00000000 00002320 0000001e 01 04 0098 00000000 00002320 0000001e
0000 0034 0000 0034
82 82 82 82 82 82 80 81 81 81 81 81 81 00 00 50 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 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 0003 0005 07 000000
0004 0010 00000000 fedcba9876543210 0004 0010 00000000 fedcba9876543210
0005 0005 01 000000 0005 0005 01 000000
0006 0010 80000408 5a5a5a5a5a5a5a5a" 0006 0010 80000408 5a5a5a5a5a5a5a5a
0007 0009 0102030405 00000000000000
"
], [0], [dnl ], [0], [dnl
NXT_PACKET_IN2 (xid=0x0): table_id=7 cookie=0xfedcba9876543210 total_len=64 metadata=0x5a5a5a5a5a5a5a5a (via action) data_len=48 buffer=0x00000114 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 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 AT_CLEANUP

View File

@ -3353,8 +3353,8 @@ OFPT_BARRIER_REPLY (OF1.1):
OVS_VSWITCHD_STOP OVS_VSWITCHD_STOP
AT_CLEANUP AT_CLEANUP
dnl This test checks that metadata is encoded in NXT_PACKET_IN2. dnl This test checks that metadata and userdata are encoded in NXT_PACKET_IN2.
AT_SETUP([ofproto - packet-out with metadata (NXT_PACKET_IN2)]) AT_SETUP([ofproto - packet-out with metadata and userdata (NXT_PACKET_IN2)])
OVS_VSWITCHD_START OVS_VSWITCHD_START
# Start a monitor listening for packet-ins. # 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]) AT_CAPTURE_FILE([monitor.log])
# Send a packet-out with a load action to set some metadata, and forward to controller # 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. # Stop the monitor and check its output.
ovs-appctl -t ovs-ofctl ofctl/barrier 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 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) 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 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: OFPT_BARRIER_REPLY:
]) ])

View File

@ -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 connection will only have a nonzero connection ID if its
controller uses the \fBNXT_SET_CONTROLLER_ID\fR Nicira extension to controller uses the \fBNXT_SET_CONTROLLER_ID\fR Nicira extension to
OpenFlow. 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 .RE
.IP .IP
Any \fIreason\fR other than \fBaction\fR and any nonzero If any \fIreason\fR other than \fBaction\fR or any nonzero
\fIcontroller-id\fR uses a Nicira vendor extension that, as of this \fIcontroller-id\fR is supplied, Open vSwitch extension
writing, is only known to be implemented by Open vSwitch (version 1.6 \fBNXAST_CONTROLLER\fR, supported by Open vSwitch 1.6 and later, is
or later). used. If \fBuserdata\fR is supplied, then \fBNXAST_CONTROLLER2\fR,
supported by Open vSwitch 2.6 and later, is used.
. .
.IP \fBcontroller\fR .IP \fBcontroller\fR
.IQ \fBcontroller\fR[\fB:\fInbytes\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" .IP "\fBnxt_packet_in2\fR"
This uses the \fBNXT_PACKET_IN2\fR message, which is extensible and 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 should avoid the need to define new formats later. In particular,
and later support this format. 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 .RE
.IP .IP