2
0
mirror of https://github.com/openvswitch/ovs synced 2025-10-25 15:07:05 +00:00

ovs-ofctl: Add "packet-out" command.

I don't expect this to be widely useful.  An upcoming commit will add a
use in unit tests.

Signed-off-by: Ben Pfaff <blp@nicira.com>
This commit is contained in:
Ben Pfaff
2012-01-25 16:30:28 -08:00
parent a993007bee
commit 0c3d5fc89a
5 changed files with 84 additions and 5 deletions

View File

@@ -384,6 +384,17 @@ learn_parse_spec(const char *orig, char *name, char *value,
}
}
/* Parses 'arg' as a set of arguments to the "learn" action and appends a
* matching NXAST_LEARN action to 'b'. The format parsed is described in
* ovs-ofctl(8).
*
* Prints an error on stderr and aborts the program if 'arg' syntax is invalid.
*
* If 'flow' is nonnull, then it should be the flow from a cls_rule that is
* the matching rule for the learning action. This helps to better validate
* the action's arguments.
*
* Modifies 'arg'. */
void
learn_parse(struct ofpbuf *b, char *arg, const struct flow *flow)
{
@@ -429,7 +440,7 @@ learn_parse(struct ofpbuf *b, char *arg, const struct flow *flow)
/* Check prerequisites. */
if (spec.src_type == NX_LEARN_SRC_FIELD
&& !mf_are_prereqs_ok(spec.src.field, flow)) {
&& flow && !mf_are_prereqs_ok(spec.src.field, flow)) {
ovs_fatal(0, "%s: cannot specify source field %s because "
"prerequisites are not satisfied",
orig, spec.src.field->name);
@@ -487,10 +498,12 @@ learn_parse(struct ofpbuf *b, char *arg, const struct flow *flow)
learn->len = htons(b->size - learn_ofs);
/* In theory the above should have caught any errors, but... */
if (flow) {
error = learn_check(learn, flow);
if (error) {
ovs_fatal(0, "%s: %s", orig, ofperr_to_string(error));
}
}
free(orig);
}

View File

@@ -625,6 +625,19 @@ parse_ofp_str(struct ofputil_flow_mod *fm, int command, const char *str_,
free(string);
}
/* Parses 's' as a set of OpenFlow actions and appends the actions to
* 'actions'.
*
* Prints an error on stderr and aborts the program if 's' syntax is
* invalid. */
void
parse_ofp_actions(const char *s_, struct ofpbuf *actions)
{
char *s = xstrdup(s_);
str_to_action(NULL, s, actions);
free(s);
}
/* Parses 'string' as an OFPT_FLOW_MOD or NXT_FLOW_MOD with command 'command'
* (one of OFPFC_*) and appends the parsed OpenFlow message to 'packets'.
* '*cur_format' should initially contain the flow format currently configured

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2011 Nicira Networks.
* Copyright (c) 2010, 2011, 2012 Nicira Networks.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -42,4 +42,7 @@ bool parse_ofp_flow_mod_file(struct list *packets,
void parse_ofp_flow_stats_request_str(struct ofputil_flow_stats_request *,
bool aggregate, char *string);
void parse_ofp_actions(const char *, struct ofpbuf *actions);
#endif /* ofp-parse.h */

View File

@@ -216,6 +216,15 @@ For this command, an exit status of 0 means that no differences were
found, 1 means that an error occurred, and 2 means that some
differences were found.
.
.IP "\fBpacket\-out \fIswitch in_port actions packet\fR..."
Connects to \fIswitch\fR and instructs it to execute the OpenFlow
\fIactions\fR on each \fIpacket\fR. For the purpose of executing the
actions, the packets are considered to have arrived on \fIin_port\fR,
which may be an OpenFlow assigned port number, an OpenFlow port name
(e.g. \fBeth0\fR), the keyword \fBlocal\fR for the OpenFlow ``local''
port \fBOFPP_LOCAL\fR, or the keyword \fBnone\fR to indicate that the
packet was generated by the switch itself.
.
.SS "OpenFlow Switch Monitoring Commands"
.
.IP "\fBsnoop \fIswitch\fR"

View File

@@ -45,6 +45,7 @@
#include "ofproto/ofproto.h"
#include "openflow/nicira-ext.h"
#include "openflow/openflow.h"
#include "packets.h"
#include "poll-loop.h"
#include "random.h"
#include "stream-ssl.h"
@@ -209,6 +210,8 @@ usage(void)
" del-flows SWITCH [FLOW] delete matching FLOWs\n"
" replace-flows SWITCH FILE replace flows with those in FILE\n"
" diff-flows SOURCE1 SOURCE2 compare flows from two sources\n"
" packet-out SWITCH IN_PORT ACTIONS PACKET...\n"
" execute ACTIONS on PACKET\n"
" monitor SWITCH [MISSLEN] [invalid_ttl]\n"
" print packets received from SWITCH\n"
" snoop SWITCH snoop on SWITCH and its controller\n"
@@ -953,6 +956,43 @@ do_probe(int argc OVS_UNUSED, char *argv[])
vconn_close(vconn);
}
static void
do_packet_out(int argc, char *argv[])
{
struct ofputil_packet_out po;
struct ofpbuf actions;
struct vconn *vconn;
int i;
ofpbuf_init(&actions, sizeof(union ofp_action));
parse_ofp_actions(argv[3], &actions);
po.buffer_id = UINT32_MAX;
po.in_port = (!strcasecmp(argv[2], "none") ? OFPP_NONE
: !strcasecmp(argv[2], "local") ? OFPP_LOCAL
: str_to_port_no(argv[1], argv[2]));
po.actions = actions.data;
po.n_actions = actions.size / sizeof(union ofp_action);
open_vconn(argv[1], &vconn);
for (i = 4; i < argc; i++) {
struct ofpbuf *packet, *opo;
const char *error_msg;
error_msg = eth_from_hex(argv[i], &packet);
if (error_msg) {
ovs_fatal(0, "%s", error_msg);
}
po.packet = packet->data;
po.packet_len = packet->size;
opo = ofputil_encode_packet_out(&po);
transact_noreply(vconn, opo);
ofpbuf_delete(packet);
}
vconn_close(vconn);
}
static void
do_mod_port(int argc OVS_UNUSED, char *argv[])
{
@@ -1682,6 +1722,7 @@ static const struct command all_commands[] = {
{ "del-flows", 1, 2, do_del_flows },
{ "replace-flows", 2, 2, do_replace_flows },
{ "diff-flows", 2, 2, do_diff_flows },
{ "packet-out", 4, INT_MAX, do_packet_out },
{ "dump-ports", 1, 2, do_dump_ports },
{ "mod-port", 3, 3, do_mod_port },
{ "get-frags", 1, 1, do_get_frags },