2009-07-08 13:19:16 -07:00
|
|
|
|
/*
|
ofp-actions: Fix variable length meta-flow OXMs.
Previously, if a flow action that involves a tunnel metadata meta-flow
field is dumped from vswitchd, the replied field length in the OXM header
is filled with the maximum possible field length, instead of the length
configured in the tunnel TLV mapping table. To solve this issue, this patch
introduces the following changes.
In order to maintain the correct length of variable length mf_fields (i.e.
tun_metadata), this patch creates a per-switch based map (struct vl_mff_map)
that hosts the variable length mf_fields. This map is updated when a
controller adds/deletes tlv-mapping entries to/from a switch. Although the
per-swtch based vl_mff_map only hosts tun_metadata for now, it is able to
support new variable length mf_fields in the future.
With this commit, when a switch decodes a flow action with mf_field, the switch
firstly looks up the global mf_fields map to identify the mf_field type. For
the variable length mf_fields, the switch uses the vl_mff_map to get the
configured mf_field entries. By lookig up vl_mff_map, the switch can check
if the added flow action access beyond the configured size of a variable
length mf_field, and the switch reports an ofperr if the controller adds a flow
with unmapped variable length mf_field. Later on, when a controller request
flows from the switch, with the per-switch based mf_fields, the switch will
encode the OXM header with correct length for variable length mf_fields.
To use the vl_mff_map for decoding flow actions, extract-ofp-actions is
updated to pass the vl_mff_map to the required action decoding functions.
Also, a new error code is introduced to identify a flow with an invalid
variable length mf_field. Moreover, a testcase is added to prevent future
regressions.
Committer notes:
- Factor out common code
- Style fixups
- Rename OFPERR_NXFMFC_INVALID_VL_MFF -> OFPERR_NXFMFC_INVALID_TLV_FIELD
VMWare-BZ: #1768370
Reported-by: Harold Lim <haroldl@vmware.com>
Suggested-by: Joe Stringer <joe@ovn.org>
Suggested-by: Jarno Rajahalme <jarno@ovn.org>
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: Joe Stringer <joe@ovn.org>
2017-01-20 15:12:21 -08:00
|
|
|
|
* Copyright (c) 2008-2017 Nicira, Inc.
|
2009-07-08 13:19:16 -07:00
|
|
|
|
*
|
2009-06-15 15:11:30 -07:00
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
|
* You may obtain a copy of the License at:
|
2009-07-08 13:19:16 -07:00
|
|
|
|
*
|
2009-06-15 15:11:30 -07:00
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
*
|
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
|
* limitations under the License.
|
2009-07-08 13:19:16 -07:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
2017-08-08 16:11:46 -07:00
|
|
|
|
#include "openvswitch/ofp-print.h"
|
|
|
|
|
|
2009-07-08 13:19:16 -07:00
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <inttypes.h>
|
2010-02-12 12:51:36 -08:00
|
|
|
|
#include <sys/types.h>
|
2009-07-08 13:19:16 -07:00
|
|
|
|
#include <netinet/in.h>
|
|
|
|
|
#include <sys/wait.h>
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
|
2011-06-10 17:45:45 -07:00
|
|
|
|
#include "bundle.h"
|
2010-10-28 17:13:18 -07:00
|
|
|
|
#include "byte-order.h"
|
2016-03-02 15:56:18 +01:00
|
|
|
|
#include "colors.h"
|
2009-07-08 13:19:16 -07:00
|
|
|
|
#include "compiler.h"
|
2016-04-14 15:20:21 -07:00
|
|
|
|
#include "dp-packet.h"
|
2009-07-08 13:19:16 -07:00
|
|
|
|
#include "flow.h"
|
2011-09-12 16:19:57 -07:00
|
|
|
|
#include "learn.h"
|
2010-12-17 14:38:50 -08:00
|
|
|
|
#include "multipath.h"
|
2012-02-15 16:33:04 -08:00
|
|
|
|
#include "netdev.h"
|
2010-12-07 13:22:46 -08:00
|
|
|
|
#include "nx-match.h"
|
2016-04-14 15:20:21 -07:00
|
|
|
|
#include "odp-util.h"
|
2009-07-08 13:19:16 -07:00
|
|
|
|
#include "openflow/nicira-ext.h"
|
2016-04-14 15:20:19 -07:00
|
|
|
|
#include "openflow/openflow.h"
|
2016-04-04 21:32:10 -04:00
|
|
|
|
#include "openvswitch/dynamic-string.h"
|
|
|
|
|
#include "openvswitch/meta-flow.h"
|
2016-04-14 15:20:19 -07:00
|
|
|
|
#include "openvswitch/ofp-actions.h"
|
2018-02-09 10:04:26 -08:00
|
|
|
|
#include "openvswitch/ofp-bundle.h"
|
|
|
|
|
#include "openvswitch/ofp-connection.h"
|
2016-03-03 10:20:43 -08:00
|
|
|
|
#include "openvswitch/ofp-errors.h"
|
2018-02-09 10:04:26 -08:00
|
|
|
|
#include "openvswitch/ofp-group.h"
|
|
|
|
|
#include "openvswitch/ofp-ipfix.h"
|
|
|
|
|
#include "openvswitch/ofp-match.h"
|
|
|
|
|
#include "openvswitch/ofp-meter.h"
|
|
|
|
|
#include "openvswitch/ofp-monitor.h"
|
2016-04-04 21:32:10 -04:00
|
|
|
|
#include "openvswitch/ofp-msgs.h"
|
2018-02-09 10:04:26 -08:00
|
|
|
|
#include "openvswitch/ofp-port.h"
|
|
|
|
|
#include "openvswitch/ofp-queue.h"
|
|
|
|
|
#include "openvswitch/ofp-switch.h"
|
|
|
|
|
#include "openvswitch/ofp-table.h"
|
2016-04-04 21:32:10 -04:00
|
|
|
|
#include "openvswitch/ofp-util.h"
|
|
|
|
|
#include "openvswitch/ofpbuf.h"
|
|
|
|
|
#include "openvswitch/type-props.h"
|
2009-07-08 13:19:16 -07:00
|
|
|
|
#include "packets.h"
|
2011-01-18 11:50:56 -08:00
|
|
|
|
#include "unaligned.h"
|
2009-07-08 13:19:16 -07:00
|
|
|
|
#include "util.h"
|
2016-04-04 21:32:04 -04:00
|
|
|
|
#include "uuid.h"
|
2009-07-08 13:19:16 -07:00
|
|
|
|
|
2010-09-16 15:36:57 -07:00
|
|
|
|
static void ofp_print_queue_name(struct ds *string, uint32_t port);
|
2012-01-12 15:48:19 -08:00
|
|
|
|
static void ofp_print_error(struct ds *, enum ofperr);
|
2009-07-08 13:19:16 -07:00
|
|
|
|
|
|
|
|
|
/* Returns a string that represents the contents of the Ethernet frame in the
|
2011-12-21 12:59:28 -08:00
|
|
|
|
* 'len' bytes starting at 'data'. The caller must free the returned string.*/
|
2009-07-08 13:19:16 -07:00
|
|
|
|
char *
|
2017-04-25 16:29:59 +00:00
|
|
|
|
ofp_packet_to_string(const void *data, size_t len, ovs_be32 packet_type)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
|
|
|
|
struct ds ds = DS_EMPTY_INITIALIZER;
|
2015-02-22 03:21:09 -08:00
|
|
|
|
struct dp_packet buf;
|
2011-12-21 12:59:28 -08:00
|
|
|
|
struct flow flow;
|
2014-03-25 15:26:23 -07:00
|
|
|
|
size_t l4_size;
|
2009-07-08 13:19:16 -07:00
|
|
|
|
|
2015-02-22 03:21:09 -08:00
|
|
|
|
dp_packet_use_const(&buf, data, len);
|
2017-04-25 16:29:59 +00:00
|
|
|
|
buf.packet_type = packet_type;
|
2015-02-22 03:21:09 -08:00
|
|
|
|
flow_extract(&buf, &flow);
|
2017-05-31 16:06:12 -07:00
|
|
|
|
flow_format(&ds, &flow, NULL);
|
2011-12-20 19:56:43 -08:00
|
|
|
|
|
2015-02-22 03:21:09 -08:00
|
|
|
|
l4_size = dp_packet_l4_size(&buf);
|
2014-03-25 15:26:23 -07:00
|
|
|
|
|
|
|
|
|
if (flow.nw_proto == IPPROTO_TCP && l4_size >= TCP_HEADER_LEN) {
|
2015-02-22 03:21:09 -08:00
|
|
|
|
struct tcp_header *th = dp_packet_l4(&buf);
|
2014-03-25 15:26:23 -07:00
|
|
|
|
ds_put_format(&ds, " tcp_csum:%"PRIx16, ntohs(th->tcp_csum));
|
|
|
|
|
} else if (flow.nw_proto == IPPROTO_UDP && l4_size >= UDP_HEADER_LEN) {
|
2015-02-22 03:21:09 -08:00
|
|
|
|
struct udp_header *uh = dp_packet_l4(&buf);
|
2014-03-25 15:26:23 -07:00
|
|
|
|
ds_put_format(&ds, " udp_csum:%"PRIx16, ntohs(uh->udp_csum));
|
|
|
|
|
} else if (flow.nw_proto == IPPROTO_SCTP && l4_size >= SCTP_HEADER_LEN) {
|
2015-02-22 03:21:09 -08:00
|
|
|
|
struct sctp_header *sh = dp_packet_l4(&buf);
|
2014-04-04 20:21:15 -07:00
|
|
|
|
ds_put_format(&ds, " sctp_csum:%"PRIx32,
|
|
|
|
|
ntohl(get_16aligned_be32(&sh->sctp_csum)));
|
2014-12-23 23:42:05 +00:00
|
|
|
|
} else if (flow.nw_proto == IPPROTO_ICMP && l4_size >= ICMP_HEADER_LEN) {
|
2015-02-22 03:21:09 -08:00
|
|
|
|
struct icmp_header *icmph = dp_packet_l4(&buf);
|
2014-12-23 23:42:05 +00:00
|
|
|
|
ds_put_format(&ds, " icmp_csum:%"PRIx16,
|
|
|
|
|
ntohs(icmph->icmp_csum));
|
|
|
|
|
} else if (flow.nw_proto == IPPROTO_ICMPV6 && l4_size >= ICMP6_HEADER_LEN) {
|
2015-02-22 03:21:09 -08:00
|
|
|
|
struct icmp6_header *icmp6h = dp_packet_l4(&buf);
|
2014-12-23 23:42:05 +00:00
|
|
|
|
ds_put_format(&ds, " icmp6_csum:%"PRIx16,
|
|
|
|
|
ntohs(icmp6h->icmp6_cksum));
|
2011-12-20 19:56:43 -08:00
|
|
|
|
}
|
|
|
|
|
|
2011-12-21 12:59:28 -08:00
|
|
|
|
ds_put_char(&ds, '\n');
|
2009-07-08 13:19:16 -07:00
|
|
|
|
|
|
|
|
|
return ds_cstr(&ds);
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-25 16:29:59 +00:00
|
|
|
|
char *
|
|
|
|
|
ofp_dp_packet_to_string(const struct dp_packet *packet)
|
|
|
|
|
{
|
|
|
|
|
return ofp_packet_to_string(dp_packet_data(packet),
|
|
|
|
|
dp_packet_size(packet),
|
|
|
|
|
packet->packet_type);
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-19 15:53:26 -08:00
|
|
|
|
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]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2011-12-22 16:35:23 -08:00
|
|
|
|
ofp_print_packet_in(struct ds *string, const struct ofp_header *oh,
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
const struct ofputil_port_map *port_map,
|
|
|
|
|
const struct ofputil_table_map *table_map, int verbosity)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
2013-04-16 15:13:21 -07:00
|
|
|
|
char reasonbuf[OFPUTIL_PACKET_IN_REASON_BUFSIZE];
|
Implement serializing the state of packet traversal in "continuations".
One purpose of OpenFlow packet-in messages is to allow a controller to
interpose on the path of a packet through the flow tables. If, for
example, the controller needs to modify a packet in some way that the
switch doesn't directly support, the controller should be able to
program the switch to send it the packet, then modify the packet and
send it back to the switch to continue through the flow table.
That's the theory. In practice, this doesn't work with any but the
simplest flow tables. Packet-in messages simply don't include enough
context to allow the flow table traversal to continue. For example:
* Via "resubmit" actions, an Open vSwitch packet can have an
effective "call stack", but a packet-in can't describe it, and
so it would be lost.
* A packet-in can't preserve the stack used by NXAST_PUSH and
NXAST_POP actions.
* A packet-in can't preserve the OpenFlow 1.1+ action set.
* A packet-in can't preserve the state of Open vSwitch mirroring
or connection tracking.
This commit introduces a solution called "continuations". A continuation
is the state of a packet's traversal through OpenFlow flow tables. A
"controller" action with the "pause" flag, which is newly implemented in
this commit, generates a continuation and sends it to the OpenFlow
controller in a packet-in asynchronous message (only NXT_PACKET_IN2
supports continuations, so the controller must configure them with
NXT_SET_PACKET_IN_FORMAT). The controller processes the packet-in,
possibly modifying some of its data, and sends it back to the switch with
an NXT_RESUME request, which causes flow table traversal to continue. In
principle, a single packet can be paused and resumed multiple times.
Another way to look at it is:
- "pause" is an extension of the existing OFPAT_CONTROLLER
action. It sends the packet to the controller, with full
pipeline context (some of which is switch implementation
dependent, and may thus vary from switch to switch).
- A continuation is an extension of OFPT_PACKET_IN, allowing for
implementation dependent metadata.
- NXT_RESUME is an extension of OFPT_PACKET_OUT, with the
semantics that the pipeline processing is continued with the
original translation context from where it was left at the time
it was paused.
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Jarno Rajahalme <jarno@ovn.org>
2016-02-19 16:10:06 -08:00
|
|
|
|
struct ofputil_packet_in_private pin;
|
2017-07-30 17:40:32 -07:00
|
|
|
|
const struct ofputil_packet_in *public = &pin.base;
|
openflow: Better abstract handling of packet-in messages.
Packet-in messages have been a bit of a mess. First, their abstraction
in the form of struct ofputil_packet_in has some fields that are used
in a clear way for incoming and outgoing packet-ins, and others
(packet_len, total_len, buffer_id) have have confusing meanings or
usage pattern depending on their direction.
Second, it's very confusing how a packet-in has both a reason (OFPR_*)
and a miss type (OFPROTO_PACKET_IN_*) and how those add up to the
actual reason that is used "on the wire" for each OpenFlow version (and
even whether the packet-in is sent at all!).
Finally, there's all kind of low-level detail randomly scattered between
connmgr, ofproto-dpif-xlate, and ofp-util.
This commit attempts to clear up some of the confusion. It simplifies
the struct ofputil_packet_in abstraction by removing the members that
didn't have a clear and consistent meaning between incoming and outgoing
packet-ins. It gets rid of OFPROTO_PACKET_IN_*, instead adding a couple
of nonstandard OFPR_* reasons that add up to what OFPROTO_PACKET_IN_*
was meant to say (in what I hope is a clearer way). And it consolidates
the tricky parts into ofp-util, where I hope it will be easier to
understand all in one place.
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Jarno Rajahalme <jarno@ovn.org>
2016-01-20 09:57:16 -08:00
|
|
|
|
uint32_t buffer_id;
|
|
|
|
|
size_t total_len;
|
Implement serializing the state of packet traversal in "continuations".
One purpose of OpenFlow packet-in messages is to allow a controller to
interpose on the path of a packet through the flow tables. If, for
example, the controller needs to modify a packet in some way that the
switch doesn't directly support, the controller should be able to
program the switch to send it the packet, then modify the packet and
send it back to the switch to continue through the flow table.
That's the theory. In practice, this doesn't work with any but the
simplest flow tables. Packet-in messages simply don't include enough
context to allow the flow table traversal to continue. For example:
* Via "resubmit" actions, an Open vSwitch packet can have an
effective "call stack", but a packet-in can't describe it, and
so it would be lost.
* A packet-in can't preserve the stack used by NXAST_PUSH and
NXAST_POP actions.
* A packet-in can't preserve the OpenFlow 1.1+ action set.
* A packet-in can't preserve the state of Open vSwitch mirroring
or connection tracking.
This commit introduces a solution called "continuations". A continuation
is the state of a packet's traversal through OpenFlow flow tables. A
"controller" action with the "pause" flag, which is newly implemented in
this commit, generates a continuation and sends it to the OpenFlow
controller in a packet-in asynchronous message (only NXT_PACKET_IN2
supports continuations, so the controller must configure them with
NXT_SET_PACKET_IN_FORMAT). The controller processes the packet-in,
possibly modifying some of its data, and sends it back to the switch with
an NXT_RESUME request, which causes flow table traversal to continue. In
principle, a single packet can be paused and resumed multiple times.
Another way to look at it is:
- "pause" is an extension of the existing OFPAT_CONTROLLER
action. It sends the packet to the controller, with full
pipeline context (some of which is switch implementation
dependent, and may thus vary from switch to switch).
- A continuation is an extension of OFPT_PACKET_IN, allowing for
implementation dependent metadata.
- NXT_RESUME is an extension of OFPT_PACKET_OUT, with the
semantics that the pipeline processing is continued with the
original translation context from where it was left at the time
it was paused.
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Jarno Rajahalme <jarno@ovn.org>
2016-02-19 16:10:06 -08:00
|
|
|
|
enum ofperr error;
|
2009-07-08 13:19:16 -07:00
|
|
|
|
|
2017-03-13 11:28:20 -07:00
|
|
|
|
error = ofputil_decode_packet_in_private(oh, true, NULL, NULL,
|
Implement serializing the state of packet traversal in "continuations".
One purpose of OpenFlow packet-in messages is to allow a controller to
interpose on the path of a packet through the flow tables. If, for
example, the controller needs to modify a packet in some way that the
switch doesn't directly support, the controller should be able to
program the switch to send it the packet, then modify the packet and
send it back to the switch to continue through the flow table.
That's the theory. In practice, this doesn't work with any but the
simplest flow tables. Packet-in messages simply don't include enough
context to allow the flow table traversal to continue. For example:
* Via "resubmit" actions, an Open vSwitch packet can have an
effective "call stack", but a packet-in can't describe it, and
so it would be lost.
* A packet-in can't preserve the stack used by NXAST_PUSH and
NXAST_POP actions.
* A packet-in can't preserve the OpenFlow 1.1+ action set.
* A packet-in can't preserve the state of Open vSwitch mirroring
or connection tracking.
This commit introduces a solution called "continuations". A continuation
is the state of a packet's traversal through OpenFlow flow tables. A
"controller" action with the "pause" flag, which is newly implemented in
this commit, generates a continuation and sends it to the OpenFlow
controller in a packet-in asynchronous message (only NXT_PACKET_IN2
supports continuations, so the controller must configure them with
NXT_SET_PACKET_IN_FORMAT). The controller processes the packet-in,
possibly modifying some of its data, and sends it back to the switch with
an NXT_RESUME request, which causes flow table traversal to continue. In
principle, a single packet can be paused and resumed multiple times.
Another way to look at it is:
- "pause" is an extension of the existing OFPAT_CONTROLLER
action. It sends the packet to the controller, with full
pipeline context (some of which is switch implementation
dependent, and may thus vary from switch to switch).
- A continuation is an extension of OFPT_PACKET_IN, allowing for
implementation dependent metadata.
- NXT_RESUME is an extension of OFPT_PACKET_OUT, with the
semantics that the pipeline processing is continued with the
original translation context from where it was left at the time
it was paused.
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Jarno Rajahalme <jarno@ovn.org>
2016-02-19 16:10:06 -08:00
|
|
|
|
&pin, &total_len, &buffer_id);
|
2011-12-22 16:35:23 -08:00
|
|
|
|
if (error) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return error;
|
2011-12-22 16:35:23 -08:00
|
|
|
|
}
|
|
|
|
|
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
if (public->table_id
|
|
|
|
|
|| ofputil_table_map_get_name(table_map, public->table_id)) {
|
|
|
|
|
ds_put_format(string, " table_id=");
|
|
|
|
|
ofputil_format_table(public->table_id, table_map, string);
|
2011-12-09 15:48:26 -08:00
|
|
|
|
}
|
|
|
|
|
|
Implement serializing the state of packet traversal in "continuations".
One purpose of OpenFlow packet-in messages is to allow a controller to
interpose on the path of a packet through the flow tables. If, for
example, the controller needs to modify a packet in some way that the
switch doesn't directly support, the controller should be able to
program the switch to send it the packet, then modify the packet and
send it back to the switch to continue through the flow table.
That's the theory. In practice, this doesn't work with any but the
simplest flow tables. Packet-in messages simply don't include enough
context to allow the flow table traversal to continue. For example:
* Via "resubmit" actions, an Open vSwitch packet can have an
effective "call stack", but a packet-in can't describe it, and
so it would be lost.
* A packet-in can't preserve the stack used by NXAST_PUSH and
NXAST_POP actions.
* A packet-in can't preserve the OpenFlow 1.1+ action set.
* A packet-in can't preserve the state of Open vSwitch mirroring
or connection tracking.
This commit introduces a solution called "continuations". A continuation
is the state of a packet's traversal through OpenFlow flow tables. A
"controller" action with the "pause" flag, which is newly implemented in
this commit, generates a continuation and sends it to the OpenFlow
controller in a packet-in asynchronous message (only NXT_PACKET_IN2
supports continuations, so the controller must configure them with
NXT_SET_PACKET_IN_FORMAT). The controller processes the packet-in,
possibly modifying some of its data, and sends it back to the switch with
an NXT_RESUME request, which causes flow table traversal to continue. In
principle, a single packet can be paused and resumed multiple times.
Another way to look at it is:
- "pause" is an extension of the existing OFPAT_CONTROLLER
action. It sends the packet to the controller, with full
pipeline context (some of which is switch implementation
dependent, and may thus vary from switch to switch).
- A continuation is an extension of OFPT_PACKET_IN, allowing for
implementation dependent metadata.
- NXT_RESUME is an extension of OFPT_PACKET_OUT, with the
semantics that the pipeline processing is continued with the
original translation context from where it was left at the time
it was paused.
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Jarno Rajahalme <jarno@ovn.org>
2016-02-19 16:10:06 -08:00
|
|
|
|
if (public->cookie != OVS_BE64_MAX) {
|
|
|
|
|
ds_put_format(string, " cookie=0x%"PRIx64, ntohll(public->cookie));
|
2011-12-09 15:48:26 -08:00
|
|
|
|
}
|
|
|
|
|
|
openflow: Better abstract handling of packet-in messages.
Packet-in messages have been a bit of a mess. First, their abstraction
in the form of struct ofputil_packet_in has some fields that are used
in a clear way for incoming and outgoing packet-ins, and others
(packet_len, total_len, buffer_id) have have confusing meanings or
usage pattern depending on their direction.
Second, it's very confusing how a packet-in has both a reason (OFPR_*)
and a miss type (OFPROTO_PACKET_IN_*) and how those add up to the
actual reason that is used "on the wire" for each OpenFlow version (and
even whether the packet-in is sent at all!).
Finally, there's all kind of low-level detail randomly scattered between
connmgr, ofproto-dpif-xlate, and ofp-util.
This commit attempts to clear up some of the confusion. It simplifies
the struct ofputil_packet_in abstraction by removing the members that
didn't have a clear and consistent meaning between incoming and outgoing
packet-ins. It gets rid of OFPROTO_PACKET_IN_*, instead adding a couple
of nonstandard OFPR_* reasons that add up to what OFPROTO_PACKET_IN_*
was meant to say (in what I hope is a clearer way). And it consolidates
the tricky parts into ofp-util, where I hope it will be easier to
understand all in one place.
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Jarno Rajahalme <jarno@ovn.org>
2016-01-20 09:57:16 -08:00
|
|
|
|
ds_put_format(string, " total_len=%"PRIuSIZE" ", total_len);
|
2012-01-04 16:40:13 -08:00
|
|
|
|
|
2017-05-31 16:06:12 -07:00
|
|
|
|
match_format(&public->flow_metadata, port_map,
|
|
|
|
|
string, OFP_DEFAULT_PRIORITY);
|
2013-08-06 12:57:16 -07:00
|
|
|
|
|
2012-02-09 14:06:35 -08:00
|
|
|
|
ds_put_format(string, " (via %s)",
|
Implement serializing the state of packet traversal in "continuations".
One purpose of OpenFlow packet-in messages is to allow a controller to
interpose on the path of a packet through the flow tables. If, for
example, the controller needs to modify a packet in some way that the
switch doesn't directly support, the controller should be able to
program the switch to send it the packet, then modify the packet and
send it back to the switch to continue through the flow table.
That's the theory. In practice, this doesn't work with any but the
simplest flow tables. Packet-in messages simply don't include enough
context to allow the flow table traversal to continue. For example:
* Via "resubmit" actions, an Open vSwitch packet can have an
effective "call stack", but a packet-in can't describe it, and
so it would be lost.
* A packet-in can't preserve the stack used by NXAST_PUSH and
NXAST_POP actions.
* A packet-in can't preserve the OpenFlow 1.1+ action set.
* A packet-in can't preserve the state of Open vSwitch mirroring
or connection tracking.
This commit introduces a solution called "continuations". A continuation
is the state of a packet's traversal through OpenFlow flow tables. A
"controller" action with the "pause" flag, which is newly implemented in
this commit, generates a continuation and sends it to the OpenFlow
controller in a packet-in asynchronous message (only NXT_PACKET_IN2
supports continuations, so the controller must configure them with
NXT_SET_PACKET_IN_FORMAT). The controller processes the packet-in,
possibly modifying some of its data, and sends it back to the switch with
an NXT_RESUME request, which causes flow table traversal to continue. In
principle, a single packet can be paused and resumed multiple times.
Another way to look at it is:
- "pause" is an extension of the existing OFPAT_CONTROLLER
action. It sends the packet to the controller, with full
pipeline context (some of which is switch implementation
dependent, and may thus vary from switch to switch).
- A continuation is an extension of OFPT_PACKET_IN, allowing for
implementation dependent metadata.
- NXT_RESUME is an extension of OFPT_PACKET_OUT, with the
semantics that the pipeline processing is continued with the
original translation context from where it was left at the time
it was paused.
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Jarno Rajahalme <jarno@ovn.org>
2016-02-19 16:10:06 -08:00
|
|
|
|
ofputil_packet_in_reason_to_string(public->reason,
|
openflow: Better abstract handling of packet-in messages.
Packet-in messages have been a bit of a mess. First, their abstraction
in the form of struct ofputil_packet_in has some fields that are used
in a clear way for incoming and outgoing packet-ins, and others
(packet_len, total_len, buffer_id) have have confusing meanings or
usage pattern depending on their direction.
Second, it's very confusing how a packet-in has both a reason (OFPR_*)
and a miss type (OFPROTO_PACKET_IN_*) and how those add up to the
actual reason that is used "on the wire" for each OpenFlow version (and
even whether the packet-in is sent at all!).
Finally, there's all kind of low-level detail randomly scattered between
connmgr, ofproto-dpif-xlate, and ofp-util.
This commit attempts to clear up some of the confusion. It simplifies
the struct ofputil_packet_in abstraction by removing the members that
didn't have a clear and consistent meaning between incoming and outgoing
packet-ins. It gets rid of OFPROTO_PACKET_IN_*, instead adding a couple
of nonstandard OFPR_* reasons that add up to what OFPROTO_PACKET_IN_*
was meant to say (in what I hope is a clearer way). And it consolidates
the tricky parts into ofp-util, where I hope it will be easier to
understand all in one place.
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Jarno Rajahalme <jarno@ovn.org>
2016-01-20 09:57:16 -08:00
|
|
|
|
reasonbuf,
|
2013-04-16 15:13:21 -07:00
|
|
|
|
sizeof reasonbuf));
|
2009-07-08 13:19:16 -07:00
|
|
|
|
|
Implement serializing the state of packet traversal in "continuations".
One purpose of OpenFlow packet-in messages is to allow a controller to
interpose on the path of a packet through the flow tables. If, for
example, the controller needs to modify a packet in some way that the
switch doesn't directly support, the controller should be able to
program the switch to send it the packet, then modify the packet and
send it back to the switch to continue through the flow table.
That's the theory. In practice, this doesn't work with any but the
simplest flow tables. Packet-in messages simply don't include enough
context to allow the flow table traversal to continue. For example:
* Via "resubmit" actions, an Open vSwitch packet can have an
effective "call stack", but a packet-in can't describe it, and
so it would be lost.
* A packet-in can't preserve the stack used by NXAST_PUSH and
NXAST_POP actions.
* A packet-in can't preserve the OpenFlow 1.1+ action set.
* A packet-in can't preserve the state of Open vSwitch mirroring
or connection tracking.
This commit introduces a solution called "continuations". A continuation
is the state of a packet's traversal through OpenFlow flow tables. A
"controller" action with the "pause" flag, which is newly implemented in
this commit, generates a continuation and sends it to the OpenFlow
controller in a packet-in asynchronous message (only NXT_PACKET_IN2
supports continuations, so the controller must configure them with
NXT_SET_PACKET_IN_FORMAT). The controller processes the packet-in,
possibly modifying some of its data, and sends it back to the switch with
an NXT_RESUME request, which causes flow table traversal to continue. In
principle, a single packet can be paused and resumed multiple times.
Another way to look at it is:
- "pause" is an extension of the existing OFPAT_CONTROLLER
action. It sends the packet to the controller, with full
pipeline context (some of which is switch implementation
dependent, and may thus vary from switch to switch).
- A continuation is an extension of OFPT_PACKET_IN, allowing for
implementation dependent metadata.
- NXT_RESUME is an extension of OFPT_PACKET_OUT, with the
semantics that the pipeline processing is continued with the
original translation context from where it was left at the time
it was paused.
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Jarno Rajahalme <jarno@ovn.org>
2016-02-19 16:10:06 -08:00
|
|
|
|
ds_put_format(string, " data_len=%"PRIuSIZE, public->packet_len);
|
openflow: Better abstract handling of packet-in messages.
Packet-in messages have been a bit of a mess. First, their abstraction
in the form of struct ofputil_packet_in has some fields that are used
in a clear way for incoming and outgoing packet-ins, and others
(packet_len, total_len, buffer_id) have have confusing meanings or
usage pattern depending on their direction.
Second, it's very confusing how a packet-in has both a reason (OFPR_*)
and a miss type (OFPROTO_PACKET_IN_*) and how those add up to the
actual reason that is used "on the wire" for each OpenFlow version (and
even whether the packet-in is sent at all!).
Finally, there's all kind of low-level detail randomly scattered between
connmgr, ofproto-dpif-xlate, and ofp-util.
This commit attempts to clear up some of the confusion. It simplifies
the struct ofputil_packet_in abstraction by removing the members that
didn't have a clear and consistent meaning between incoming and outgoing
packet-ins. It gets rid of OFPROTO_PACKET_IN_*, instead adding a couple
of nonstandard OFPR_* reasons that add up to what OFPROTO_PACKET_IN_*
was meant to say (in what I hope is a clearer way). And it consolidates
the tricky parts into ofp-util, where I hope it will be easier to
understand all in one place.
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Jarno Rajahalme <jarno@ovn.org>
2016-01-20 09:57:16 -08:00
|
|
|
|
if (buffer_id == UINT32_MAX) {
|
2009-07-08 13:19:16 -07:00
|
|
|
|
ds_put_format(string, " (unbuffered)");
|
Implement serializing the state of packet traversal in "continuations".
One purpose of OpenFlow packet-in messages is to allow a controller to
interpose on the path of a packet through the flow tables. If, for
example, the controller needs to modify a packet in some way that the
switch doesn't directly support, the controller should be able to
program the switch to send it the packet, then modify the packet and
send it back to the switch to continue through the flow table.
That's the theory. In practice, this doesn't work with any but the
simplest flow tables. Packet-in messages simply don't include enough
context to allow the flow table traversal to continue. For example:
* Via "resubmit" actions, an Open vSwitch packet can have an
effective "call stack", but a packet-in can't describe it, and
so it would be lost.
* A packet-in can't preserve the stack used by NXAST_PUSH and
NXAST_POP actions.
* A packet-in can't preserve the OpenFlow 1.1+ action set.
* A packet-in can't preserve the state of Open vSwitch mirroring
or connection tracking.
This commit introduces a solution called "continuations". A continuation
is the state of a packet's traversal through OpenFlow flow tables. A
"controller" action with the "pause" flag, which is newly implemented in
this commit, generates a continuation and sends it to the OpenFlow
controller in a packet-in asynchronous message (only NXT_PACKET_IN2
supports continuations, so the controller must configure them with
NXT_SET_PACKET_IN_FORMAT). The controller processes the packet-in,
possibly modifying some of its data, and sends it back to the switch with
an NXT_RESUME request, which causes flow table traversal to continue. In
principle, a single packet can be paused and resumed multiple times.
Another way to look at it is:
- "pause" is an extension of the existing OFPAT_CONTROLLER
action. It sends the packet to the controller, with full
pipeline context (some of which is switch implementation
dependent, and may thus vary from switch to switch).
- A continuation is an extension of OFPT_PACKET_IN, allowing for
implementation dependent metadata.
- NXT_RESUME is an extension of OFPT_PACKET_OUT, with the
semantics that the pipeline processing is continued with the
original translation context from where it was left at the time
it was paused.
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Jarno Rajahalme <jarno@ovn.org>
2016-02-19 16:10:06 -08:00
|
|
|
|
if (total_len != public->packet_len) {
|
2009-07-08 13:19:16 -07:00
|
|
|
|
ds_put_format(string, " (***total_len != data_len***)");
|
2011-12-22 16:35:23 -08:00
|
|
|
|
}
|
2009-07-08 13:19:16 -07:00
|
|
|
|
} else {
|
openflow: Better abstract handling of packet-in messages.
Packet-in messages have been a bit of a mess. First, their abstraction
in the form of struct ofputil_packet_in has some fields that are used
in a clear way for incoming and outgoing packet-ins, and others
(packet_len, total_len, buffer_id) have have confusing meanings or
usage pattern depending on their direction.
Second, it's very confusing how a packet-in has both a reason (OFPR_*)
and a miss type (OFPROTO_PACKET_IN_*) and how those add up to the
actual reason that is used "on the wire" for each OpenFlow version (and
even whether the packet-in is sent at all!).
Finally, there's all kind of low-level detail randomly scattered between
connmgr, ofproto-dpif-xlate, and ofp-util.
This commit attempts to clear up some of the confusion. It simplifies
the struct ofputil_packet_in abstraction by removing the members that
didn't have a clear and consistent meaning between incoming and outgoing
packet-ins. It gets rid of OFPROTO_PACKET_IN_*, instead adding a couple
of nonstandard OFPR_* reasons that add up to what OFPROTO_PACKET_IN_*
was meant to say (in what I hope is a clearer way). And it consolidates
the tricky parts into ofp-util, where I hope it will be easier to
understand all in one place.
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Jarno Rajahalme <jarno@ovn.org>
2016-01-20 09:57:16 -08:00
|
|
|
|
ds_put_format(string, " buffer=0x%08"PRIx32, buffer_id);
|
Implement serializing the state of packet traversal in "continuations".
One purpose of OpenFlow packet-in messages is to allow a controller to
interpose on the path of a packet through the flow tables. If, for
example, the controller needs to modify a packet in some way that the
switch doesn't directly support, the controller should be able to
program the switch to send it the packet, then modify the packet and
send it back to the switch to continue through the flow table.
That's the theory. In practice, this doesn't work with any but the
simplest flow tables. Packet-in messages simply don't include enough
context to allow the flow table traversal to continue. For example:
* Via "resubmit" actions, an Open vSwitch packet can have an
effective "call stack", but a packet-in can't describe it, and
so it would be lost.
* A packet-in can't preserve the stack used by NXAST_PUSH and
NXAST_POP actions.
* A packet-in can't preserve the OpenFlow 1.1+ action set.
* A packet-in can't preserve the state of Open vSwitch mirroring
or connection tracking.
This commit introduces a solution called "continuations". A continuation
is the state of a packet's traversal through OpenFlow flow tables. A
"controller" action with the "pause" flag, which is newly implemented in
this commit, generates a continuation and sends it to the OpenFlow
controller in a packet-in asynchronous message (only NXT_PACKET_IN2
supports continuations, so the controller must configure them with
NXT_SET_PACKET_IN_FORMAT). The controller processes the packet-in,
possibly modifying some of its data, and sends it back to the switch with
an NXT_RESUME request, which causes flow table traversal to continue. In
principle, a single packet can be paused and resumed multiple times.
Another way to look at it is:
- "pause" is an extension of the existing OFPAT_CONTROLLER
action. It sends the packet to the controller, with full
pipeline context (some of which is switch implementation
dependent, and may thus vary from switch to switch).
- A continuation is an extension of OFPT_PACKET_IN, allowing for
implementation dependent metadata.
- NXT_RESUME is an extension of OFPT_PACKET_OUT, with the
semantics that the pipeline processing is continued with the
original translation context from where it was left at the time
it was paused.
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Jarno Rajahalme <jarno@ovn.org>
2016-02-19 16:10:06 -08:00
|
|
|
|
if (total_len < public->packet_len) {
|
2009-07-08 13:19:16 -07:00
|
|
|
|
ds_put_format(string, " (***total_len < data_len***)");
|
2011-12-22 16:35:23 -08:00
|
|
|
|
}
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
|
|
|
|
ds_put_char(string, '\n');
|
|
|
|
|
|
Implement serializing the state of packet traversal in "continuations".
One purpose of OpenFlow packet-in messages is to allow a controller to
interpose on the path of a packet through the flow tables. If, for
example, the controller needs to modify a packet in some way that the
switch doesn't directly support, the controller should be able to
program the switch to send it the packet, then modify the packet and
send it back to the switch to continue through the flow table.
That's the theory. In practice, this doesn't work with any but the
simplest flow tables. Packet-in messages simply don't include enough
context to allow the flow table traversal to continue. For example:
* Via "resubmit" actions, an Open vSwitch packet can have an
effective "call stack", but a packet-in can't describe it, and
so it would be lost.
* A packet-in can't preserve the stack used by NXAST_PUSH and
NXAST_POP actions.
* A packet-in can't preserve the OpenFlow 1.1+ action set.
* A packet-in can't preserve the state of Open vSwitch mirroring
or connection tracking.
This commit introduces a solution called "continuations". A continuation
is the state of a packet's traversal through OpenFlow flow tables. A
"controller" action with the "pause" flag, which is newly implemented in
this commit, generates a continuation and sends it to the OpenFlow
controller in a packet-in asynchronous message (only NXT_PACKET_IN2
supports continuations, so the controller must configure them with
NXT_SET_PACKET_IN_FORMAT). The controller processes the packet-in,
possibly modifying some of its data, and sends it back to the switch with
an NXT_RESUME request, which causes flow table traversal to continue. In
principle, a single packet can be paused and resumed multiple times.
Another way to look at it is:
- "pause" is an extension of the existing OFPAT_CONTROLLER
action. It sends the packet to the controller, with full
pipeline context (some of which is switch implementation
dependent, and may thus vary from switch to switch).
- A continuation is an extension of OFPT_PACKET_IN, allowing for
implementation dependent metadata.
- NXT_RESUME is an extension of OFPT_PACKET_OUT, with the
semantics that the pipeline processing is continued with the
original translation context from where it was left at the time
it was paused.
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Jarno Rajahalme <jarno@ovn.org>
2016-02-19 16:10:06 -08:00
|
|
|
|
if (public->userdata_len) {
|
2016-02-19 15:53:26 -08:00
|
|
|
|
ds_put_cstr(string, " userdata=");
|
2017-07-30 17:40:32 -07:00
|
|
|
|
format_hex_arg(string, pin.base.userdata, pin.base.userdata_len);
|
Implement serializing the state of packet traversal in "continuations".
One purpose of OpenFlow packet-in messages is to allow a controller to
interpose on the path of a packet through the flow tables. If, for
example, the controller needs to modify a packet in some way that the
switch doesn't directly support, the controller should be able to
program the switch to send it the packet, then modify the packet and
send it back to the switch to continue through the flow table.
That's the theory. In practice, this doesn't work with any but the
simplest flow tables. Packet-in messages simply don't include enough
context to allow the flow table traversal to continue. For example:
* Via "resubmit" actions, an Open vSwitch packet can have an
effective "call stack", but a packet-in can't describe it, and
so it would be lost.
* A packet-in can't preserve the stack used by NXAST_PUSH and
NXAST_POP actions.
* A packet-in can't preserve the OpenFlow 1.1+ action set.
* A packet-in can't preserve the state of Open vSwitch mirroring
or connection tracking.
This commit introduces a solution called "continuations". A continuation
is the state of a packet's traversal through OpenFlow flow tables. A
"controller" action with the "pause" flag, which is newly implemented in
this commit, generates a continuation and sends it to the OpenFlow
controller in a packet-in asynchronous message (only NXT_PACKET_IN2
supports continuations, so the controller must configure them with
NXT_SET_PACKET_IN_FORMAT). The controller processes the packet-in,
possibly modifying some of its data, and sends it back to the switch with
an NXT_RESUME request, which causes flow table traversal to continue. In
principle, a single packet can be paused and resumed multiple times.
Another way to look at it is:
- "pause" is an extension of the existing OFPAT_CONTROLLER
action. It sends the packet to the controller, with full
pipeline context (some of which is switch implementation
dependent, and may thus vary from switch to switch).
- A continuation is an extension of OFPT_PACKET_IN, allowing for
implementation dependent metadata.
- NXT_RESUME is an extension of OFPT_PACKET_OUT, with the
semantics that the pipeline processing is continued with the
original translation context from where it was left at the time
it was paused.
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Jarno Rajahalme <jarno@ovn.org>
2016-02-19 16:10:06 -08:00
|
|
|
|
ds_put_char(string, '\n');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!uuid_is_zero(&pin.bridge)) {
|
|
|
|
|
ds_put_format(string, " continuation.bridge="UUID_FMT"\n",
|
|
|
|
|
UUID_ARGS(&pin.bridge));
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-05 17:30:27 -08:00
|
|
|
|
if (pin.stack_size) {
|
|
|
|
|
ds_put_cstr(string, " continuation.stack=(top)");
|
|
|
|
|
|
|
|
|
|
struct ofpbuf pin_stack;
|
|
|
|
|
ofpbuf_use_const(&pin_stack, pin.stack, pin.stack_size);
|
|
|
|
|
|
|
|
|
|
while (pin_stack.size) {
|
|
|
|
|
uint8_t len;
|
|
|
|
|
uint8_t *val = nx_stack_pop(&pin_stack, &len);
|
|
|
|
|
union mf_subvalue value;
|
|
|
|
|
|
|
|
|
|
ds_put_char(string, ' ');
|
|
|
|
|
memset(&value, 0, sizeof value - len);
|
|
|
|
|
memcpy(&value.u8[sizeof value - len], val, len);
|
|
|
|
|
mf_subvalue_format(&value, string);
|
Implement serializing the state of packet traversal in "continuations".
One purpose of OpenFlow packet-in messages is to allow a controller to
interpose on the path of a packet through the flow tables. If, for
example, the controller needs to modify a packet in some way that the
switch doesn't directly support, the controller should be able to
program the switch to send it the packet, then modify the packet and
send it back to the switch to continue through the flow table.
That's the theory. In practice, this doesn't work with any but the
simplest flow tables. Packet-in messages simply don't include enough
context to allow the flow table traversal to continue. For example:
* Via "resubmit" actions, an Open vSwitch packet can have an
effective "call stack", but a packet-in can't describe it, and
so it would be lost.
* A packet-in can't preserve the stack used by NXAST_PUSH and
NXAST_POP actions.
* A packet-in can't preserve the OpenFlow 1.1+ action set.
* A packet-in can't preserve the state of Open vSwitch mirroring
or connection tracking.
This commit introduces a solution called "continuations". A continuation
is the state of a packet's traversal through OpenFlow flow tables. A
"controller" action with the "pause" flag, which is newly implemented in
this commit, generates a continuation and sends it to the OpenFlow
controller in a packet-in asynchronous message (only NXT_PACKET_IN2
supports continuations, so the controller must configure them with
NXT_SET_PACKET_IN_FORMAT). The controller processes the packet-in,
possibly modifying some of its data, and sends it back to the switch with
an NXT_RESUME request, which causes flow table traversal to continue. In
principle, a single packet can be paused and resumed multiple times.
Another way to look at it is:
- "pause" is an extension of the existing OFPAT_CONTROLLER
action. It sends the packet to the controller, with full
pipeline context (some of which is switch implementation
dependent, and may thus vary from switch to switch).
- A continuation is an extension of OFPT_PACKET_IN, allowing for
implementation dependent metadata.
- NXT_RESUME is an extension of OFPT_PACKET_OUT, with the
semantics that the pipeline processing is continued with the
original translation context from where it was left at the time
it was paused.
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Jarno Rajahalme <jarno@ovn.org>
2016-02-19 16:10:06 -08:00
|
|
|
|
}
|
2017-01-05 17:30:27 -08:00
|
|
|
|
ds_put_cstr(string, " (bottom)\n");
|
Implement serializing the state of packet traversal in "continuations".
One purpose of OpenFlow packet-in messages is to allow a controller to
interpose on the path of a packet through the flow tables. If, for
example, the controller needs to modify a packet in some way that the
switch doesn't directly support, the controller should be able to
program the switch to send it the packet, then modify the packet and
send it back to the switch to continue through the flow table.
That's the theory. In practice, this doesn't work with any but the
simplest flow tables. Packet-in messages simply don't include enough
context to allow the flow table traversal to continue. For example:
* Via "resubmit" actions, an Open vSwitch packet can have an
effective "call stack", but a packet-in can't describe it, and
so it would be lost.
* A packet-in can't preserve the stack used by NXAST_PUSH and
NXAST_POP actions.
* A packet-in can't preserve the OpenFlow 1.1+ action set.
* A packet-in can't preserve the state of Open vSwitch mirroring
or connection tracking.
This commit introduces a solution called "continuations". A continuation
is the state of a packet's traversal through OpenFlow flow tables. A
"controller" action with the "pause" flag, which is newly implemented in
this commit, generates a continuation and sends it to the OpenFlow
controller in a packet-in asynchronous message (only NXT_PACKET_IN2
supports continuations, so the controller must configure them with
NXT_SET_PACKET_IN_FORMAT). The controller processes the packet-in,
possibly modifying some of its data, and sends it back to the switch with
an NXT_RESUME request, which causes flow table traversal to continue. In
principle, a single packet can be paused and resumed multiple times.
Another way to look at it is:
- "pause" is an extension of the existing OFPAT_CONTROLLER
action. It sends the packet to the controller, with full
pipeline context (some of which is switch implementation
dependent, and may thus vary from switch to switch).
- A continuation is an extension of OFPT_PACKET_IN, allowing for
implementation dependent metadata.
- NXT_RESUME is an extension of OFPT_PACKET_OUT, with the
semantics that the pipeline processing is continued with the
original translation context from where it was left at the time
it was paused.
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Jarno Rajahalme <jarno@ovn.org>
2016-02-19 16:10:06 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pin.mirrors) {
|
|
|
|
|
ds_put_format(string, " continuation.mirrors=0x%"PRIx32"\n",
|
|
|
|
|
pin.mirrors);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pin.conntracked) {
|
|
|
|
|
ds_put_cstr(string, " continuation.conntracked=true\n");
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-12 12:56:12 -08:00
|
|
|
|
struct ofpact_format_params fp = {
|
|
|
|
|
.port_map = port_map,
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
.table_map = table_map,
|
2018-01-12 12:56:12 -08:00
|
|
|
|
.s = string,
|
|
|
|
|
};
|
|
|
|
|
|
Implement serializing the state of packet traversal in "continuations".
One purpose of OpenFlow packet-in messages is to allow a controller to
interpose on the path of a packet through the flow tables. If, for
example, the controller needs to modify a packet in some way that the
switch doesn't directly support, the controller should be able to
program the switch to send it the packet, then modify the packet and
send it back to the switch to continue through the flow table.
That's the theory. In practice, this doesn't work with any but the
simplest flow tables. Packet-in messages simply don't include enough
context to allow the flow table traversal to continue. For example:
* Via "resubmit" actions, an Open vSwitch packet can have an
effective "call stack", but a packet-in can't describe it, and
so it would be lost.
* A packet-in can't preserve the stack used by NXAST_PUSH and
NXAST_POP actions.
* A packet-in can't preserve the OpenFlow 1.1+ action set.
* A packet-in can't preserve the state of Open vSwitch mirroring
or connection tracking.
This commit introduces a solution called "continuations". A continuation
is the state of a packet's traversal through OpenFlow flow tables. A
"controller" action with the "pause" flag, which is newly implemented in
this commit, generates a continuation and sends it to the OpenFlow
controller in a packet-in asynchronous message (only NXT_PACKET_IN2
supports continuations, so the controller must configure them with
NXT_SET_PACKET_IN_FORMAT). The controller processes the packet-in,
possibly modifying some of its data, and sends it back to the switch with
an NXT_RESUME request, which causes flow table traversal to continue. In
principle, a single packet can be paused and resumed multiple times.
Another way to look at it is:
- "pause" is an extension of the existing OFPAT_CONTROLLER
action. It sends the packet to the controller, with full
pipeline context (some of which is switch implementation
dependent, and may thus vary from switch to switch).
- A continuation is an extension of OFPT_PACKET_IN, allowing for
implementation dependent metadata.
- NXT_RESUME is an extension of OFPT_PACKET_OUT, with the
semantics that the pipeline processing is continued with the
original translation context from where it was left at the time
it was paused.
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Jarno Rajahalme <jarno@ovn.org>
2016-02-19 16:10:06 -08:00
|
|
|
|
if (pin.actions_len) {
|
|
|
|
|
ds_put_cstr(string, " continuation.actions=");
|
2018-01-12 12:56:12 -08:00
|
|
|
|
ofpacts_format(pin.actions, pin.actions_len, &fp);
|
Implement serializing the state of packet traversal in "continuations".
One purpose of OpenFlow packet-in messages is to allow a controller to
interpose on the path of a packet through the flow tables. If, for
example, the controller needs to modify a packet in some way that the
switch doesn't directly support, the controller should be able to
program the switch to send it the packet, then modify the packet and
send it back to the switch to continue through the flow table.
That's the theory. In practice, this doesn't work with any but the
simplest flow tables. Packet-in messages simply don't include enough
context to allow the flow table traversal to continue. For example:
* Via "resubmit" actions, an Open vSwitch packet can have an
effective "call stack", but a packet-in can't describe it, and
so it would be lost.
* A packet-in can't preserve the stack used by NXAST_PUSH and
NXAST_POP actions.
* A packet-in can't preserve the OpenFlow 1.1+ action set.
* A packet-in can't preserve the state of Open vSwitch mirroring
or connection tracking.
This commit introduces a solution called "continuations". A continuation
is the state of a packet's traversal through OpenFlow flow tables. A
"controller" action with the "pause" flag, which is newly implemented in
this commit, generates a continuation and sends it to the OpenFlow
controller in a packet-in asynchronous message (only NXT_PACKET_IN2
supports continuations, so the controller must configure them with
NXT_SET_PACKET_IN_FORMAT). The controller processes the packet-in,
possibly modifying some of its data, and sends it back to the switch with
an NXT_RESUME request, which causes flow table traversal to continue. In
principle, a single packet can be paused and resumed multiple times.
Another way to look at it is:
- "pause" is an extension of the existing OFPAT_CONTROLLER
action. It sends the packet to the controller, with full
pipeline context (some of which is switch implementation
dependent, and may thus vary from switch to switch).
- A continuation is an extension of OFPT_PACKET_IN, allowing for
implementation dependent metadata.
- NXT_RESUME is an extension of OFPT_PACKET_OUT, with the
semantics that the pipeline processing is continued with the
original translation context from where it was left at the time
it was paused.
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Jarno Rajahalme <jarno@ovn.org>
2016-02-19 16:10:06 -08:00
|
|
|
|
ds_put_char(string, '\n');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pin.action_set_len) {
|
|
|
|
|
ds_put_cstr(string, " continuation.action_set=");
|
2018-01-12 12:56:12 -08:00
|
|
|
|
ofpacts_format(pin.action_set, pin.action_set_len, &fp);
|
2016-02-19 15:53:26 -08:00
|
|
|
|
ds_put_char(string, '\n');
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-08 13:19:16 -07:00
|
|
|
|
if (verbosity > 0) {
|
2017-06-23 16:48:38 +00:00
|
|
|
|
char *packet = ofp_packet_to_string(
|
|
|
|
|
public->packet, public->packet_len,
|
|
|
|
|
public->flow_metadata.flow.packet_type);
|
2009-07-08 13:19:16 -07:00
|
|
|
|
ds_put_cstr(string, packet);
|
|
|
|
|
free(packet);
|
|
|
|
|
}
|
2013-05-17 14:14:14 +09:00
|
|
|
|
if (verbosity > 2) {
|
Implement serializing the state of packet traversal in "continuations".
One purpose of OpenFlow packet-in messages is to allow a controller to
interpose on the path of a packet through the flow tables. If, for
example, the controller needs to modify a packet in some way that the
switch doesn't directly support, the controller should be able to
program the switch to send it the packet, then modify the packet and
send it back to the switch to continue through the flow table.
That's the theory. In practice, this doesn't work with any but the
simplest flow tables. Packet-in messages simply don't include enough
context to allow the flow table traversal to continue. For example:
* Via "resubmit" actions, an Open vSwitch packet can have an
effective "call stack", but a packet-in can't describe it, and
so it would be lost.
* A packet-in can't preserve the stack used by NXAST_PUSH and
NXAST_POP actions.
* A packet-in can't preserve the OpenFlow 1.1+ action set.
* A packet-in can't preserve the state of Open vSwitch mirroring
or connection tracking.
This commit introduces a solution called "continuations". A continuation
is the state of a packet's traversal through OpenFlow flow tables. A
"controller" action with the "pause" flag, which is newly implemented in
this commit, generates a continuation and sends it to the OpenFlow
controller in a packet-in asynchronous message (only NXT_PACKET_IN2
supports continuations, so the controller must configure them with
NXT_SET_PACKET_IN_FORMAT). The controller processes the packet-in,
possibly modifying some of its data, and sends it back to the switch with
an NXT_RESUME request, which causes flow table traversal to continue. In
principle, a single packet can be paused and resumed multiple times.
Another way to look at it is:
- "pause" is an extension of the existing OFPAT_CONTROLLER
action. It sends the packet to the controller, with full
pipeline context (some of which is switch implementation
dependent, and may thus vary from switch to switch).
- A continuation is an extension of OFPT_PACKET_IN, allowing for
implementation dependent metadata.
- NXT_RESUME is an extension of OFPT_PACKET_OUT, with the
semantics that the pipeline processing is continued with the
original translation context from where it was left at the time
it was paused.
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Jarno Rajahalme <jarno@ovn.org>
2016-02-19 16:10:06 -08:00
|
|
|
|
ds_put_hex_dump(string, public->packet, public->packet_len, 0, false);
|
2013-05-17 14:14:14 +09:00
|
|
|
|
}
|
Implement serializing the state of packet traversal in "continuations".
One purpose of OpenFlow packet-in messages is to allow a controller to
interpose on the path of a packet through the flow tables. If, for
example, the controller needs to modify a packet in some way that the
switch doesn't directly support, the controller should be able to
program the switch to send it the packet, then modify the packet and
send it back to the switch to continue through the flow table.
That's the theory. In practice, this doesn't work with any but the
simplest flow tables. Packet-in messages simply don't include enough
context to allow the flow table traversal to continue. For example:
* Via "resubmit" actions, an Open vSwitch packet can have an
effective "call stack", but a packet-in can't describe it, and
so it would be lost.
* A packet-in can't preserve the stack used by NXAST_PUSH and
NXAST_POP actions.
* A packet-in can't preserve the OpenFlow 1.1+ action set.
* A packet-in can't preserve the state of Open vSwitch mirroring
or connection tracking.
This commit introduces a solution called "continuations". A continuation
is the state of a packet's traversal through OpenFlow flow tables. A
"controller" action with the "pause" flag, which is newly implemented in
this commit, generates a continuation and sends it to the OpenFlow
controller in a packet-in asynchronous message (only NXT_PACKET_IN2
supports continuations, so the controller must configure them with
NXT_SET_PACKET_IN_FORMAT). The controller processes the packet-in,
possibly modifying some of its data, and sends it back to the switch with
an NXT_RESUME request, which causes flow table traversal to continue. In
principle, a single packet can be paused and resumed multiple times.
Another way to look at it is:
- "pause" is an extension of the existing OFPAT_CONTROLLER
action. It sends the packet to the controller, with full
pipeline context (some of which is switch implementation
dependent, and may thus vary from switch to switch).
- A continuation is an extension of OFPT_PACKET_IN, allowing for
implementation dependent metadata.
- NXT_RESUME is an extension of OFPT_PACKET_OUT, with the
semantics that the pipeline processing is continued with the
original translation context from where it was left at the time
it was paused.
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Jarno Rajahalme <jarno@ovn.org>
2016-02-19 16:10:06 -08:00
|
|
|
|
|
|
|
|
|
ofputil_packet_in_private_destroy(&pin);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
|
|
|
|
|
return 0;
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2012-07-19 23:23:17 -07:00
|
|
|
|
ofp_print_packet_out(struct ds *string, const struct ofp_header *oh,
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
const struct ofputil_port_map *port_map,
|
|
|
|
|
const struct ofputil_table_map *table_map, int verbosity)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
2012-02-06 14:17:49 -08:00
|
|
|
|
struct ofputil_packet_out po;
|
2012-07-03 22:17:14 -07:00
|
|
|
|
struct ofpbuf ofpacts;
|
2012-02-06 14:17:49 -08:00
|
|
|
|
enum ofperr error;
|
2009-07-08 13:19:16 -07:00
|
|
|
|
|
2012-07-03 22:17:14 -07:00
|
|
|
|
ofpbuf_init(&ofpacts, 64);
|
2017-05-15 10:04:59 -07:00
|
|
|
|
error = ofputil_decode_packet_out(&po, oh, NULL, &ofpacts);
|
2012-02-06 14:17:49 -08:00
|
|
|
|
if (error) {
|
2012-07-03 22:17:14 -07:00
|
|
|
|
ofpbuf_uninit(&ofpacts);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return error;
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
2012-02-06 14:17:49 -08:00
|
|
|
|
|
2017-05-15 10:04:55 -07:00
|
|
|
|
ds_put_char(string, ' ');
|
2017-05-31 16:06:12 -07:00
|
|
|
|
match_format(&po.flow_metadata, port_map, string, OFP_DEFAULT_PRIORITY);
|
2012-02-06 14:17:49 -08:00
|
|
|
|
|
2013-10-14 14:08:20 -07:00
|
|
|
|
ds_put_cstr(string, " actions=");
|
2018-01-12 12:56:12 -08:00
|
|
|
|
struct ofpact_format_params fp = {
|
|
|
|
|
.port_map = port_map,
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
.table_map = table_map,
|
2018-01-12 12:56:12 -08:00
|
|
|
|
.s = string,
|
|
|
|
|
};
|
|
|
|
|
ofpacts_format(po.ofpacts, po.ofpacts_len, &fp);
|
2012-02-06 14:17:49 -08:00
|
|
|
|
|
|
|
|
|
if (po.buffer_id == UINT32_MAX) {
|
2013-11-25 23:38:48 -08:00
|
|
|
|
ds_put_format(string, " data_len=%"PRIuSIZE, po.packet_len);
|
2012-02-06 14:17:49 -08:00
|
|
|
|
if (verbosity > 0 && po.packet_len > 0) {
|
2017-06-23 16:48:47 +00:00
|
|
|
|
ovs_be32 po_packet_type = po.flow_metadata.flow.packet_type;
|
2017-04-25 16:29:59 +00:00
|
|
|
|
char *packet = ofp_packet_to_string(po.packet, po.packet_len,
|
2017-06-23 16:48:47 +00:00
|
|
|
|
po_packet_type);
|
2009-07-08 13:19:16 -07:00
|
|
|
|
ds_put_char(string, '\n');
|
|
|
|
|
ds_put_cstr(string, packet);
|
|
|
|
|
free(packet);
|
|
|
|
|
}
|
2013-05-17 14:14:14 +09:00
|
|
|
|
if (verbosity > 2) {
|
|
|
|
|
ds_put_hex_dump(string, po.packet, po.packet_len, 0, false);
|
|
|
|
|
}
|
2009-07-08 13:19:16 -07:00
|
|
|
|
} else {
|
2012-02-06 14:17:49 -08:00
|
|
|
|
ds_put_format(string, " buffer=0x%08"PRIx32, po.buffer_id);
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
2012-07-03 22:17:14 -07:00
|
|
|
|
|
|
|
|
|
ofpbuf_uninit(&ofpacts);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return 0;
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* qsort comparison function. */
|
|
|
|
|
static int
|
|
|
|
|
compare_ports(const void *a_, const void *b_)
|
|
|
|
|
{
|
2012-02-15 16:33:04 -08:00
|
|
|
|
const struct ofputil_phy_port *a = a_;
|
|
|
|
|
const struct ofputil_phy_port *b = b_;
|
2013-06-19 16:58:44 -07:00
|
|
|
|
uint16_t ap = ofp_to_u16(a->port_no);
|
|
|
|
|
uint16_t bp = ofp_to_u16(b->port_no);
|
2009-07-08 13:19:16 -07:00
|
|
|
|
|
|
|
|
|
return ap < bp ? -1 : ap > bp;
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-14 15:17:33 -07:00
|
|
|
|
static void
|
|
|
|
|
ofp_print_bit_names(struct ds *string, uint32_t bits,
|
2012-06-29 16:23:43 -07:00
|
|
|
|
const char *(*bit_to_name)(uint32_t bit),
|
|
|
|
|
char separator)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
2011-07-14 15:17:33 -07:00
|
|
|
|
int n = 0;
|
2012-02-15 16:33:04 -08:00
|
|
|
|
int i;
|
2011-07-14 15:17:33 -07:00
|
|
|
|
|
|
|
|
|
if (!bits) {
|
|
|
|
|
ds_put_cstr(string, "0");
|
2009-07-08 13:19:16 -07:00
|
|
|
|
return;
|
|
|
|
|
}
|
2011-07-14 15:17:33 -07:00
|
|
|
|
|
2012-02-15 16:33:04 -08:00
|
|
|
|
for (i = 0; i < 32; i++) {
|
|
|
|
|
uint32_t bit = UINT32_C(1) << i;
|
|
|
|
|
|
|
|
|
|
if (bits & bit) {
|
|
|
|
|
const char *name = bit_to_name(bit);
|
|
|
|
|
if (name) {
|
|
|
|
|
if (n++) {
|
2012-06-29 16:23:43 -07:00
|
|
|
|
ds_put_char(string, separator);
|
2012-02-15 16:33:04 -08:00
|
|
|
|
}
|
|
|
|
|
ds_put_cstr(string, name);
|
|
|
|
|
bits &= ~bit;
|
2011-07-14 15:17:33 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
2011-07-14 15:17:33 -07:00
|
|
|
|
|
|
|
|
|
if (bits) {
|
2012-05-13 16:34:49 -07:00
|
|
|
|
if (n) {
|
2012-06-29 16:23:43 -07:00
|
|
|
|
ds_put_char(string, separator);
|
2011-07-14 15:17:33 -07:00
|
|
|
|
}
|
|
|
|
|
ds_put_format(string, "0x%"PRIx32, bits);
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
2011-07-14 15:17:33 -07:00
|
|
|
|
}
|
|
|
|
|
|
2012-02-15 16:33:04 -08:00
|
|
|
|
static const char *
|
|
|
|
|
netdev_feature_to_name(uint32_t bit)
|
|
|
|
|
{
|
|
|
|
|
enum netdev_features f = bit;
|
|
|
|
|
|
|
|
|
|
switch (f) {
|
|
|
|
|
case NETDEV_F_10MB_HD: return "10MB-HD";
|
|
|
|
|
case NETDEV_F_10MB_FD: return "10MB-FD";
|
|
|
|
|
case NETDEV_F_100MB_HD: return "100MB-HD";
|
|
|
|
|
case NETDEV_F_100MB_FD: return "100MB-FD";
|
|
|
|
|
case NETDEV_F_1GB_HD: return "1GB-HD";
|
|
|
|
|
case NETDEV_F_1GB_FD: return "1GB-FD";
|
|
|
|
|
case NETDEV_F_10GB_FD: return "10GB-FD";
|
|
|
|
|
case NETDEV_F_40GB_FD: return "40GB-FD";
|
|
|
|
|
case NETDEV_F_100GB_FD: return "100GB-FD";
|
|
|
|
|
case NETDEV_F_1TB_FD: return "1TB-FD";
|
|
|
|
|
case NETDEV_F_OTHER: return "OTHER";
|
|
|
|
|
case NETDEV_F_COPPER: return "COPPER";
|
|
|
|
|
case NETDEV_F_FIBER: return "FIBER";
|
|
|
|
|
case NETDEV_F_AUTONEG: return "AUTO_NEG";
|
|
|
|
|
case NETDEV_F_PAUSE: return "AUTO_PAUSE";
|
|
|
|
|
case NETDEV_F_PAUSE_ASYM: return "AUTO_PAUSE_ASYM";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-14 15:17:33 -07:00
|
|
|
|
static void
|
2012-02-15 16:33:04 -08:00
|
|
|
|
ofp_print_port_features(struct ds *string, enum netdev_features features)
|
2011-07-14 15:17:33 -07:00
|
|
|
|
{
|
2012-06-29 16:23:43 -07:00
|
|
|
|
ofp_print_bit_names(string, features, netdev_feature_to_name, ' ');
|
2011-07-14 15:17:33 -07:00
|
|
|
|
ds_put_char(string, '\n');
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-15 16:33:04 -08:00
|
|
|
|
static const char *
|
|
|
|
|
ofputil_port_config_to_name(uint32_t bit)
|
|
|
|
|
{
|
|
|
|
|
enum ofputil_port_config pc = bit;
|
|
|
|
|
|
|
|
|
|
switch (pc) {
|
|
|
|
|
case OFPUTIL_PC_PORT_DOWN: return "PORT_DOWN";
|
|
|
|
|
case OFPUTIL_PC_NO_STP: return "NO_STP";
|
|
|
|
|
case OFPUTIL_PC_NO_RECV: return "NO_RECV";
|
|
|
|
|
case OFPUTIL_PC_NO_RECV_STP: return "NO_RECV_STP";
|
|
|
|
|
case OFPUTIL_PC_NO_FLOOD: return "NO_FLOOD";
|
|
|
|
|
case OFPUTIL_PC_NO_FWD: return "NO_FWD";
|
|
|
|
|
case OFPUTIL_PC_NO_PACKET_IN: return "NO_PACKET_IN";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-14 15:17:33 -07:00
|
|
|
|
static void
|
2012-02-15 16:33:04 -08:00
|
|
|
|
ofp_print_port_config(struct ds *string, enum ofputil_port_config config)
|
2011-07-14 15:17:33 -07:00
|
|
|
|
{
|
2012-06-29 16:23:43 -07:00
|
|
|
|
ofp_print_bit_names(string, config, ofputil_port_config_to_name, ' ');
|
2011-07-14 15:17:33 -07:00
|
|
|
|
ds_put_char(string, '\n');
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-15 16:33:04 -08:00
|
|
|
|
static const char *
|
|
|
|
|
ofputil_port_state_to_name(uint32_t bit)
|
|
|
|
|
{
|
|
|
|
|
enum ofputil_port_state ps = bit;
|
|
|
|
|
|
|
|
|
|
switch (ps) {
|
|
|
|
|
case OFPUTIL_PS_LINK_DOWN: return "LINK_DOWN";
|
|
|
|
|
case OFPUTIL_PS_BLOCKED: return "BLOCKED";
|
|
|
|
|
case OFPUTIL_PS_LIVE: return "LIVE";
|
|
|
|
|
|
|
|
|
|
case OFPUTIL_PS_STP_LISTEN:
|
|
|
|
|
case OFPUTIL_PS_STP_LEARN:
|
|
|
|
|
case OFPUTIL_PS_STP_FORWARD:
|
|
|
|
|
case OFPUTIL_PS_STP_BLOCK:
|
|
|
|
|
/* Handled elsewhere. */
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-14 15:17:33 -07:00
|
|
|
|
static void
|
2012-02-15 16:33:04 -08:00
|
|
|
|
ofp_print_port_state(struct ds *string, enum ofputil_port_state state)
|
2011-07-14 15:17:33 -07:00
|
|
|
|
{
|
2012-02-15 16:33:04 -08:00
|
|
|
|
enum ofputil_port_state stp_state;
|
2011-07-14 15:17:33 -07:00
|
|
|
|
|
|
|
|
|
/* The STP state is a 2-bit field so it doesn't fit in with the bitmask
|
|
|
|
|
* pattern. We have to special case it.
|
|
|
|
|
*
|
|
|
|
|
* OVS doesn't support STP, so this field will always be 0 if we are
|
|
|
|
|
* talking to OVS, so we'd always print STP_LISTEN in that case.
|
|
|
|
|
* Therefore, we don't print anything at all if the value is STP_LISTEN, to
|
|
|
|
|
* avoid confusing users. */
|
2012-02-15 16:33:04 -08:00
|
|
|
|
stp_state = state & OFPUTIL_PS_STP_MASK;
|
2011-07-14 15:17:33 -07:00
|
|
|
|
if (stp_state) {
|
2012-02-15 16:33:04 -08:00
|
|
|
|
ds_put_cstr(string,
|
|
|
|
|
(stp_state == OFPUTIL_PS_STP_LEARN ? "STP_LEARN"
|
|
|
|
|
: stp_state == OFPUTIL_PS_STP_FORWARD ? "STP_FORWARD"
|
|
|
|
|
: "STP_BLOCK"));
|
|
|
|
|
state &= ~OFPUTIL_PS_STP_MASK;
|
2011-07-14 15:17:33 -07:00
|
|
|
|
if (state) {
|
2012-06-29 16:23:43 -07:00
|
|
|
|
ofp_print_bit_names(string, state, ofputil_port_state_to_name,
|
|
|
|
|
' ');
|
2011-07-14 15:17:33 -07:00
|
|
|
|
}
|
|
|
|
|
} else {
|
2012-06-29 16:23:43 -07:00
|
|
|
|
ofp_print_bit_names(string, state, ofputil_port_state_to_name, ' ');
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
|
|
|
|
ds_put_char(string, '\n');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2012-02-15 16:33:04 -08:00
|
|
|
|
ofp_print_phy_port(struct ds *string, const struct ofputil_phy_port *port)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
2012-02-15 16:33:04 -08:00
|
|
|
|
char name[sizeof port->name];
|
2009-07-08 13:19:16 -07:00
|
|
|
|
int j;
|
|
|
|
|
|
|
|
|
|
memcpy(name, port->name, sizeof name);
|
|
|
|
|
for (j = 0; j < sizeof name - 1; j++) {
|
2011-04-15 09:31:36 -07:00
|
|
|
|
if (!isprint((unsigned char) name[j])) {
|
2009-07-08 13:19:16 -07:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
name[j] = '\0';
|
|
|
|
|
|
|
|
|
|
ds_put_char(string, ' ');
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ofputil_format_port(port->port_no, NULL, string);
|
2011-07-14 15:17:33 -07:00
|
|
|
|
ds_put_format(string, "(%s): addr:"ETH_ADDR_FMT"\n",
|
|
|
|
|
name, ETH_ADDR_ARGS(port->hw_addr));
|
|
|
|
|
|
2017-04-05 23:08:09 -07:00
|
|
|
|
if (!eth_addr64_is_zero(port->hw_addr64)) {
|
|
|
|
|
ds_put_format(string, " addr64: "ETH_ADDR64_FMT"\n",
|
|
|
|
|
ETH_ADDR64_ARGS(port->hw_addr64));
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-14 15:17:33 -07:00
|
|
|
|
ds_put_cstr(string, " config: ");
|
2012-02-15 16:33:04 -08:00
|
|
|
|
ofp_print_port_config(string, port->config);
|
2011-07-14 15:17:33 -07:00
|
|
|
|
|
|
|
|
|
ds_put_cstr(string, " state: ");
|
2012-02-15 16:33:04 -08:00
|
|
|
|
ofp_print_port_state(string, port->state);
|
2011-07-14 15:17:33 -07:00
|
|
|
|
|
2009-07-08 13:19:16 -07:00
|
|
|
|
if (port->curr) {
|
|
|
|
|
ds_put_format(string, " current: ");
|
2012-02-15 16:33:04 -08:00
|
|
|
|
ofp_print_port_features(string, port->curr);
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
|
|
|
|
if (port->advertised) {
|
|
|
|
|
ds_put_format(string, " advertised: ");
|
2012-02-15 16:33:04 -08:00
|
|
|
|
ofp_print_port_features(string, port->advertised);
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
|
|
|
|
if (port->supported) {
|
|
|
|
|
ds_put_format(string, " supported: ");
|
2012-02-15 16:33:04 -08:00
|
|
|
|
ofp_print_port_features(string, port->supported);
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
|
|
|
|
if (port->peer) {
|
|
|
|
|
ds_put_format(string, " peer: ");
|
2012-02-15 16:33:04 -08:00
|
|
|
|
ofp_print_port_features(string, port->peer);
|
|
|
|
|
}
|
|
|
|
|
ds_put_format(string, " speed: %"PRIu32" Mbps now, "
|
|
|
|
|
"%"PRIu32" Mbps max\n",
|
|
|
|
|
port->curr_speed / UINT32_C(1000),
|
|
|
|
|
port->max_speed / UINT32_C(1000));
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-04 14:42:04 -07:00
|
|
|
|
/* Given a buffer 'b' that contains an array of OpenFlow ports of type
|
|
|
|
|
* 'ofp_version', writes a detailed description of each port into
|
|
|
|
|
* 'string'. */
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2012-05-04 14:42:04 -07:00
|
|
|
|
ofp_print_phy_ports(struct ds *string, uint8_t ofp_version,
|
|
|
|
|
struct ofpbuf *b)
|
|
|
|
|
{
|
|
|
|
|
struct ofputil_phy_port *ports;
|
2014-05-07 21:39:00 -07:00
|
|
|
|
size_t allocated_ports, n_ports;
|
|
|
|
|
int retval;
|
2012-05-04 14:42:04 -07:00
|
|
|
|
size_t i;
|
|
|
|
|
|
2014-05-07 21:39:00 -07:00
|
|
|
|
ports = NULL;
|
|
|
|
|
allocated_ports = 0;
|
|
|
|
|
for (n_ports = 0; ; n_ports++) {
|
|
|
|
|
if (n_ports >= allocated_ports) {
|
|
|
|
|
ports = x2nrealloc(ports, &allocated_ports, sizeof *ports);
|
|
|
|
|
}
|
2012-05-04 14:42:04 -07:00
|
|
|
|
|
2014-05-07 21:39:00 -07:00
|
|
|
|
retval = ofputil_pull_phy_port(ofp_version, b, &ports[n_ports]);
|
|
|
|
|
if (retval) {
|
|
|
|
|
break;
|
2012-05-04 14:42:04 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
2014-05-07 21:39:00 -07:00
|
|
|
|
|
2012-05-04 14:42:04 -07:00
|
|
|
|
qsort(ports, n_ports, sizeof *ports, compare_ports);
|
|
|
|
|
for (i = 0; i < n_ports; i++) {
|
|
|
|
|
ofp_print_phy_port(string, &ports[i]);
|
|
|
|
|
}
|
|
|
|
|
free(ports);
|
2014-05-07 21:39:00 -07:00
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return retval != EOF ? retval : 0;
|
2012-05-04 14:42:04 -07:00
|
|
|
|
}
|
|
|
|
|
|
2012-02-15 16:33:04 -08:00
|
|
|
|
static const char *
|
|
|
|
|
ofputil_capabilities_to_name(uint32_t bit)
|
|
|
|
|
{
|
|
|
|
|
enum ofputil_capabilities capabilities = bit;
|
|
|
|
|
|
|
|
|
|
switch (capabilities) {
|
|
|
|
|
case OFPUTIL_C_FLOW_STATS: return "FLOW_STATS";
|
|
|
|
|
case OFPUTIL_C_TABLE_STATS: return "TABLE_STATS";
|
|
|
|
|
case OFPUTIL_C_PORT_STATS: return "PORT_STATS";
|
|
|
|
|
case OFPUTIL_C_IP_REASM: return "IP_REASM";
|
|
|
|
|
case OFPUTIL_C_QUEUE_STATS: return "QUEUE_STATS";
|
|
|
|
|
case OFPUTIL_C_ARP_MATCH_IP: return "ARP_MATCH_IP";
|
|
|
|
|
case OFPUTIL_C_STP: return "STP";
|
|
|
|
|
case OFPUTIL_C_GROUP_STATS: return "GROUP_STATS";
|
2012-07-30 11:03:03 +09:00
|
|
|
|
case OFPUTIL_C_PORT_BLOCKED: return "PORT_BLOCKED";
|
2016-11-14 13:24:55 -08:00
|
|
|
|
case OFPUTIL_C_BUNDLES: return "BUNDLES";
|
|
|
|
|
case OFPUTIL_C_FLOW_MONITORING: return "FLOW_MONITORING";
|
2012-02-15 16:33:04 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2012-07-19 23:23:17 -07:00
|
|
|
|
ofp_print_switch_features(struct ds *string, const struct ofp_header *oh)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
2012-02-15 16:33:04 -08:00
|
|
|
|
struct ofputil_switch_features features;
|
2016-02-18 15:13:09 -08:00
|
|
|
|
struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
|
|
|
|
|
enum ofperr error = ofputil_pull_switch_features(&b, &features);
|
2012-02-15 16:33:04 -08:00
|
|
|
|
if (error) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return error;
|
2012-02-15 16:33:04 -08:00
|
|
|
|
}
|
2009-07-08 13:19:16 -07:00
|
|
|
|
|
2012-02-15 16:33:04 -08:00
|
|
|
|
ds_put_format(string, " dpid:%016"PRIx64"\n", features.datapath_id);
|
2012-11-27 17:44:22 +02:00
|
|
|
|
|
|
|
|
|
ds_put_format(string, "n_tables:%"PRIu8", n_buffers:%"PRIu32,
|
2012-02-15 16:33:04 -08:00
|
|
|
|
features.n_tables, features.n_buffers);
|
2012-11-27 17:44:22 +02:00
|
|
|
|
if (features.auxiliary_id) {
|
|
|
|
|
ds_put_format(string, ", auxiliary_id:%"PRIu8, features.auxiliary_id);
|
|
|
|
|
}
|
|
|
|
|
ds_put_char(string, '\n');
|
2009-07-08 13:19:16 -07:00
|
|
|
|
|
2012-02-15 16:33:04 -08:00
|
|
|
|
ds_put_cstr(string, "capabilities: ");
|
|
|
|
|
ofp_print_bit_names(string, features.capabilities,
|
2012-06-29 16:23:43 -07:00
|
|
|
|
ofputil_capabilities_to_name, ' ');
|
2012-02-15 16:33:04 -08:00
|
|
|
|
ds_put_char(string, '\n');
|
|
|
|
|
|
2012-07-30 11:03:00 +09:00
|
|
|
|
switch ((enum ofp_version)oh->version) {
|
|
|
|
|
case OFP10_VERSION:
|
|
|
|
|
ds_put_cstr(string, "actions: ");
|
2014-08-11 10:57:03 -07:00
|
|
|
|
ofpact_bitmap_format(features.ofpacts, string);
|
2012-07-30 11:03:00 +09:00
|
|
|
|
ds_put_char(string, '\n');
|
|
|
|
|
break;
|
|
|
|
|
case OFP11_VERSION:
|
|
|
|
|
case OFP12_VERSION:
|
|
|
|
|
break;
|
2012-11-27 17:44:22 +02:00
|
|
|
|
case OFP13_VERSION:
|
2014-03-03 15:22:32 +02:00
|
|
|
|
case OFP14_VERSION:
|
2014-05-07 13:42:24 -07:00
|
|
|
|
case OFP15_VERSION:
|
2016-04-10 14:39:12 -07:00
|
|
|
|
case OFP16_VERSION:
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return 0; /* no ports in ofp13_switch_features */
|
2012-07-30 11:03:00 +09:00
|
|
|
|
default:
|
2013-12-17 10:32:12 -08:00
|
|
|
|
OVS_NOT_REACHED();
|
2012-07-30 11:03:00 +09:00
|
|
|
|
}
|
2012-02-15 16:33:04 -08:00
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_phy_ports(string, oh->version, &b);
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-12-21 15:39:10 -08:00
|
|
|
|
ofp_print_switch_config(struct ds *string,
|
|
|
|
|
const struct ofputil_switch_config *config)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
2015-12-21 15:39:10 -08:00
|
|
|
|
ds_put_format(string, " frags=%s",
|
|
|
|
|
ofputil_frag_handling_to_string(config->frag));
|
2009-07-08 13:19:16 -07:00
|
|
|
|
|
2015-12-21 15:39:10 -08:00
|
|
|
|
if (config->invalid_ttl_to_controller > 0) {
|
2012-01-13 17:54:04 -08:00
|
|
|
|
ds_put_format(string, " invalid_ttl_to_controller");
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-21 15:39:10 -08:00
|
|
|
|
ds_put_format(string, " miss_send_len=%"PRIu16"\n", config->miss_send_len);
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2015-12-21 15:39:10 -08:00
|
|
|
|
ofp_print_set_config(struct ds *string, const struct ofp_header *oh)
|
|
|
|
|
{
|
|
|
|
|
struct ofputil_switch_config config;
|
|
|
|
|
enum ofperr error;
|
|
|
|
|
|
|
|
|
|
error = ofputil_decode_set_config(oh, &config);
|
|
|
|
|
if (error) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return error;
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
2015-12-21 15:39:10 -08:00
|
|
|
|
ofp_print_switch_config(string, &config);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return 0;
|
2015-12-21 15:39:10 -08:00
|
|
|
|
}
|
2009-07-08 13:19:16 -07:00
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2015-12-21 15:39:10 -08:00
|
|
|
|
ofp_print_get_config_reply(struct ds *string, const struct ofp_header *oh)
|
|
|
|
|
{
|
|
|
|
|
struct ofputil_switch_config config;
|
|
|
|
|
ofputil_decode_get_config_reply(oh, &config);
|
|
|
|
|
ofp_print_switch_config(string, &config);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return 0;
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void print_wild(struct ds *string, const char *leader, int is_wild,
|
2010-08-30 00:24:53 -07:00
|
|
|
|
int verbosity, const char *format, ...)
|
2014-12-15 14:10:38 +01:00
|
|
|
|
OVS_PRINTF_FORMAT(5, 6);
|
2009-07-08 13:19:16 -07:00
|
|
|
|
|
|
|
|
|
static void print_wild(struct ds *string, const char *leader, int is_wild,
|
2010-08-30 00:24:53 -07:00
|
|
|
|
int verbosity, const char *format, ...)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
|
|
|
|
if (is_wild && verbosity < 2) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
ds_put_cstr(string, leader);
|
|
|
|
|
if (!is_wild) {
|
|
|
|
|
va_list args;
|
|
|
|
|
|
|
|
|
|
va_start(args, format);
|
|
|
|
|
ds_put_format_valist(string, format, args);
|
|
|
|
|
va_end(args);
|
|
|
|
|
} else {
|
|
|
|
|
ds_put_char(string, '*');
|
|
|
|
|
}
|
|
|
|
|
ds_put_char(string, ',');
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-14 14:43:53 +02:00
|
|
|
|
static void
|
|
|
|
|
print_wild_port(struct ds *string, const char *leader, int is_wild,
|
2017-05-31 16:06:12 -07:00
|
|
|
|
int verbosity, ofp_port_t port,
|
|
|
|
|
const struct ofputil_port_map *port_map)
|
2013-01-14 14:43:53 +02:00
|
|
|
|
{
|
|
|
|
|
if (is_wild && verbosity < 2) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
ds_put_cstr(string, leader);
|
|
|
|
|
if (!is_wild) {
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ofputil_format_port(port, port_map, string);
|
2013-01-14 14:43:53 +02:00
|
|
|
|
} else {
|
|
|
|
|
ds_put_char(string, '*');
|
|
|
|
|
}
|
|
|
|
|
ds_put_char(string, ',');
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-08 13:19:16 -07:00
|
|
|
|
static void
|
2011-03-29 14:42:20 -07:00
|
|
|
|
print_ip_netmask(struct ds *string, const char *leader, ovs_be32 ip,
|
2009-07-08 13:19:16 -07:00
|
|
|
|
uint32_t wild_bits, int verbosity)
|
|
|
|
|
{
|
|
|
|
|
if (wild_bits >= 32 && verbosity < 2) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
ds_put_cstr(string, leader);
|
|
|
|
|
if (wild_bits < 32) {
|
2012-12-12 15:26:21 -08:00
|
|
|
|
ds_put_format(string, IP_FMT, IP_ARGS(ip));
|
2009-07-08 13:19:16 -07:00
|
|
|
|
if (wild_bits) {
|
|
|
|
|
ds_put_format(string, "/%d", 32 - wild_bits);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
ds_put_char(string, '*');
|
|
|
|
|
}
|
|
|
|
|
ds_put_char(string, ',');
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-14 13:03:57 -07:00
|
|
|
|
void
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ofp10_match_print(struct ds *f, const struct ofp10_match *om,
|
|
|
|
|
const struct ofputil_port_map *port_map, int verbosity)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
2017-05-31 16:06:12 -07:00
|
|
|
|
char *s = ofp10_match_to_string(om, port_map, verbosity);
|
2009-07-08 13:19:16 -07:00
|
|
|
|
ds_put_cstr(f, s);
|
|
|
|
|
free(s);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ofp10_match_to_string(const struct ofp10_match *om,
|
|
|
|
|
const struct ofputil_port_map *port_map, int verbosity)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
|
|
|
|
struct ds f = DS_EMPTY_INITIALIZER;
|
|
|
|
|
uint32_t w = ntohl(om->wildcards);
|
|
|
|
|
bool skip_type = false;
|
|
|
|
|
bool skip_proto = false;
|
|
|
|
|
|
2012-05-21 21:51:03 -07:00
|
|
|
|
if (!(w & OFPFW10_DL_TYPE)) {
|
2009-07-08 13:19:16 -07:00
|
|
|
|
skip_type = true;
|
|
|
|
|
if (om->dl_type == htons(ETH_TYPE_IP)) {
|
2012-05-21 21:51:03 -07:00
|
|
|
|
if (!(w & OFPFW10_NW_PROTO)) {
|
2009-07-08 13:19:16 -07:00
|
|
|
|
skip_proto = true;
|
2011-02-02 11:33:20 -08:00
|
|
|
|
if (om->nw_proto == IPPROTO_ICMP) {
|
2009-07-08 13:19:16 -07:00
|
|
|
|
ds_put_cstr(&f, "icmp,");
|
2011-02-02 11:33:20 -08:00
|
|
|
|
} else if (om->nw_proto == IPPROTO_TCP) {
|
2009-07-08 13:19:16 -07:00
|
|
|
|
ds_put_cstr(&f, "tcp,");
|
2011-02-02 11:33:20 -08:00
|
|
|
|
} else if (om->nw_proto == IPPROTO_UDP) {
|
2009-07-08 13:19:16 -07:00
|
|
|
|
ds_put_cstr(&f, "udp,");
|
2013-08-22 20:24:45 +12:00
|
|
|
|
} else if (om->nw_proto == IPPROTO_SCTP) {
|
|
|
|
|
ds_put_cstr(&f, "sctp,");
|
2009-07-08 13:19:16 -07:00
|
|
|
|
} else {
|
|
|
|
|
ds_put_cstr(&f, "ip,");
|
|
|
|
|
skip_proto = false;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
ds_put_cstr(&f, "ip,");
|
|
|
|
|
}
|
|
|
|
|
} else if (om->dl_type == htons(ETH_TYPE_ARP)) {
|
|
|
|
|
ds_put_cstr(&f, "arp,");
|
2012-11-02 11:43:46 -07:00
|
|
|
|
} else if (om->dl_type == htons(ETH_TYPE_RARP)){
|
|
|
|
|
ds_put_cstr(&f, "rarp,");
|
2013-01-25 16:22:07 +09:00
|
|
|
|
} else if (om->dl_type == htons(ETH_TYPE_MPLS)) {
|
|
|
|
|
ds_put_cstr(&f, "mpls,");
|
|
|
|
|
} else if (om->dl_type == htons(ETH_TYPE_MPLS_MCAST)) {
|
|
|
|
|
ds_put_cstr(&f, "mplsm,");
|
2009-07-08 13:19:16 -07:00
|
|
|
|
} else {
|
|
|
|
|
skip_type = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-01-14 14:43:53 +02:00
|
|
|
|
print_wild_port(&f, "in_port=", w & OFPFW10_IN_PORT, verbosity,
|
2017-05-31 16:06:12 -07:00
|
|
|
|
u16_to_ofp(ntohs(om->in_port)), port_map);
|
2012-05-21 21:51:03 -07:00
|
|
|
|
print_wild(&f, "dl_vlan=", w & OFPFW10_DL_VLAN, verbosity,
|
2010-04-10 01:20:23 -07:00
|
|
|
|
"%d", ntohs(om->dl_vlan));
|
2012-05-21 21:51:03 -07:00
|
|
|
|
print_wild(&f, "dl_vlan_pcp=", w & OFPFW10_DL_VLAN_PCP, verbosity,
|
2009-11-11 14:59:49 -08:00
|
|
|
|
"%d", om->dl_vlan_pcp);
|
2012-05-21 21:51:03 -07:00
|
|
|
|
print_wild(&f, "dl_src=", w & OFPFW10_DL_SRC, verbosity,
|
2009-07-08 13:19:16 -07:00
|
|
|
|
ETH_ADDR_FMT, ETH_ADDR_ARGS(om->dl_src));
|
2012-05-21 21:51:03 -07:00
|
|
|
|
print_wild(&f, "dl_dst=", w & OFPFW10_DL_DST, verbosity,
|
2009-07-08 13:19:16 -07:00
|
|
|
|
ETH_ADDR_FMT, ETH_ADDR_ARGS(om->dl_dst));
|
|
|
|
|
if (!skip_type) {
|
2012-05-21 21:51:03 -07:00
|
|
|
|
print_wild(&f, "dl_type=", w & OFPFW10_DL_TYPE, verbosity,
|
2009-07-08 13:19:16 -07:00
|
|
|
|
"0x%04x", ntohs(om->dl_type));
|
|
|
|
|
}
|
|
|
|
|
print_ip_netmask(&f, "nw_src=", om->nw_src,
|
2012-05-21 21:51:03 -07:00
|
|
|
|
(w & OFPFW10_NW_SRC_MASK) >> OFPFW10_NW_SRC_SHIFT,
|
|
|
|
|
verbosity);
|
2009-07-08 13:19:16 -07:00
|
|
|
|
print_ip_netmask(&f, "nw_dst=", om->nw_dst,
|
2012-05-21 21:51:03 -07:00
|
|
|
|
(w & OFPFW10_NW_DST_MASK) >> OFPFW10_NW_DST_SHIFT,
|
|
|
|
|
verbosity);
|
2009-07-08 13:19:16 -07:00
|
|
|
|
if (!skip_proto) {
|
2012-11-02 11:43:46 -07:00
|
|
|
|
if (om->dl_type == htons(ETH_TYPE_ARP) ||
|
|
|
|
|
om->dl_type == htons(ETH_TYPE_RARP)) {
|
2012-05-21 21:51:03 -07:00
|
|
|
|
print_wild(&f, "arp_op=", w & OFPFW10_NW_PROTO, verbosity,
|
2009-11-09 16:43:47 -08:00
|
|
|
|
"%u", om->nw_proto);
|
|
|
|
|
} else {
|
2012-05-21 21:51:03 -07:00
|
|
|
|
print_wild(&f, "nw_proto=", w & OFPFW10_NW_PROTO, verbosity,
|
2009-11-09 16:43:47 -08:00
|
|
|
|
"%u", om->nw_proto);
|
|
|
|
|
}
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
2012-05-21 21:51:03 -07:00
|
|
|
|
print_wild(&f, "nw_tos=", w & OFPFW10_NW_TOS, verbosity,
|
2010-11-05 10:47:50 +09:00
|
|
|
|
"%u", om->nw_tos);
|
2011-02-02 11:33:20 -08:00
|
|
|
|
if (om->nw_proto == IPPROTO_ICMP) {
|
2012-05-21 21:51:03 -07:00
|
|
|
|
print_wild(&f, "icmp_type=", w & OFPFW10_ICMP_TYPE, verbosity,
|
2011-10-05 11:06:12 -07:00
|
|
|
|
"%d", ntohs(om->tp_src));
|
2012-05-21 21:51:03 -07:00
|
|
|
|
print_wild(&f, "icmp_code=", w & OFPFW10_ICMP_CODE, verbosity,
|
2011-10-05 11:06:12 -07:00
|
|
|
|
"%d", ntohs(om->tp_dst));
|
2009-07-08 13:19:16 -07:00
|
|
|
|
} else {
|
2012-05-21 21:51:03 -07:00
|
|
|
|
print_wild(&f, "tp_src=", w & OFPFW10_TP_SRC, verbosity,
|
2009-07-08 13:19:16 -07:00
|
|
|
|
"%d", ntohs(om->tp_src));
|
2012-05-21 21:51:03 -07:00
|
|
|
|
print_wild(&f, "tp_dst=", w & OFPFW10_TP_DST, verbosity,
|
2009-07-08 13:19:16 -07:00
|
|
|
|
"%d", ntohs(om->tp_dst));
|
|
|
|
|
}
|
2014-11-04 15:14:04 +09:00
|
|
|
|
ds_chomp(&f, ',');
|
2009-07-08 13:19:16 -07:00
|
|
|
|
return ds_cstr(&f);
|
|
|
|
|
}
|
|
|
|
|
|
2012-11-27 17:44:22 +02:00
|
|
|
|
static void
|
2013-08-26 16:23:50 -07:00
|
|
|
|
ofp_print_flow_flags(struct ds *s, enum ofputil_flow_mod_flags flags)
|
2012-11-27 17:44:22 +02:00
|
|
|
|
{
|
2013-08-26 16:23:50 -07:00
|
|
|
|
if (flags & OFPUTIL_FF_SEND_FLOW_REM) {
|
2012-11-27 17:44:22 +02:00
|
|
|
|
ds_put_cstr(s, "send_flow_rem ");
|
|
|
|
|
}
|
2013-08-26 16:23:50 -07:00
|
|
|
|
if (flags & OFPUTIL_FF_CHECK_OVERLAP) {
|
2012-11-27 17:44:22 +02:00
|
|
|
|
ds_put_cstr(s, "check_overlap ");
|
|
|
|
|
}
|
2013-08-26 16:23:50 -07:00
|
|
|
|
if (flags & OFPUTIL_FF_RESET_COUNTS) {
|
2012-11-27 17:44:22 +02:00
|
|
|
|
ds_put_cstr(s, "reset_counts ");
|
|
|
|
|
}
|
2013-08-26 16:23:50 -07:00
|
|
|
|
if (flags & OFPUTIL_FF_NO_PKT_COUNTS) {
|
2012-11-27 17:44:22 +02:00
|
|
|
|
ds_put_cstr(s, "no_packet_counts ");
|
|
|
|
|
}
|
2013-08-26 16:23:50 -07:00
|
|
|
|
if (flags & OFPUTIL_FF_NO_BYT_COUNTS) {
|
2012-11-27 17:44:22 +02:00
|
|
|
|
ds_put_cstr(s, "no_byte_counts ");
|
|
|
|
|
}
|
2014-03-05 15:27:31 -08:00
|
|
|
|
if (flags & OFPUTIL_FF_HIDDEN_FIELDS) {
|
|
|
|
|
ds_put_cstr(s, "allow_hidden_fields ");
|
|
|
|
|
}
|
|
|
|
|
if (flags & OFPUTIL_FF_NO_READONLY) {
|
|
|
|
|
ds_put_cstr(s, "no_readonly_table ");
|
|
|
|
|
}
|
2012-11-27 17:44:22 +02:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ofp_print_flow_mod(struct ds *s, const struct ofp_header *oh,
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
const struct ofputil_port_map *port_map,
|
|
|
|
|
const struct ofputil_table_map *table_map, int verbosity)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
2011-08-08 14:46:38 -07:00
|
|
|
|
struct ofputil_flow_mod fm;
|
2012-07-03 22:17:14 -07:00
|
|
|
|
struct ofpbuf ofpacts;
|
2010-12-14 11:36:04 -08:00
|
|
|
|
bool need_priority;
|
2012-01-12 15:48:19 -08:00
|
|
|
|
enum ofperr error;
|
2012-07-19 23:23:17 -07:00
|
|
|
|
enum ofpraw raw;
|
2012-08-01 16:01:51 +09:00
|
|
|
|
enum ofputil_protocol protocol;
|
|
|
|
|
|
|
|
|
|
protocol = ofputil_protocol_from_ofp_version(oh->version);
|
|
|
|
|
protocol = ofputil_protocol_set_tid(protocol, true);
|
2009-07-08 13:19:16 -07:00
|
|
|
|
|
2012-07-03 22:17:14 -07:00
|
|
|
|
ofpbuf_init(&ofpacts, 64);
|
ofp-actions: Fix variable length meta-flow OXMs.
Previously, if a flow action that involves a tunnel metadata meta-flow
field is dumped from vswitchd, the replied field length in the OXM header
is filled with the maximum possible field length, instead of the length
configured in the tunnel TLV mapping table. To solve this issue, this patch
introduces the following changes.
In order to maintain the correct length of variable length mf_fields (i.e.
tun_metadata), this patch creates a per-switch based map (struct vl_mff_map)
that hosts the variable length mf_fields. This map is updated when a
controller adds/deletes tlv-mapping entries to/from a switch. Although the
per-swtch based vl_mff_map only hosts tun_metadata for now, it is able to
support new variable length mf_fields in the future.
With this commit, when a switch decodes a flow action with mf_field, the switch
firstly looks up the global mf_fields map to identify the mf_field type. For
the variable length mf_fields, the switch uses the vl_mff_map to get the
configured mf_field entries. By lookig up vl_mff_map, the switch can check
if the added flow action access beyond the configured size of a variable
length mf_field, and the switch reports an ofperr if the controller adds a flow
with unmapped variable length mf_field. Later on, when a controller request
flows from the switch, with the per-switch based mf_fields, the switch will
encode the OXM header with correct length for variable length mf_fields.
To use the vl_mff_map for decoding flow actions, extract-ofp-actions is
updated to pass the vl_mff_map to the required action decoding functions.
Also, a new error code is introduced to identify a flow with an invalid
variable length mf_field. Moreover, a testcase is added to prevent future
regressions.
Committer notes:
- Factor out common code
- Style fixups
- Rename OFPERR_NXFMFC_INVALID_VL_MFF -> OFPERR_NXFMFC_INVALID_TLV_FIELD
VMWare-BZ: #1768370
Reported-by: Harold Lim <haroldl@vmware.com>
Suggested-by: Joe Stringer <joe@ovn.org>
Suggested-by: Jarno Rajahalme <jarno@ovn.org>
Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com>
Signed-off-by: Joe Stringer <joe@ovn.org>
2017-01-20 15:12:21 -08:00
|
|
|
|
error = ofputil_decode_flow_mod(&fm, oh, protocol, NULL, NULL, &ofpacts,
|
2013-11-01 21:45:28 -07:00
|
|
|
|
OFPP_MAX, 255);
|
2010-12-07 13:22:46 -08:00
|
|
|
|
if (error) {
|
2012-07-03 22:17:14 -07:00
|
|
|
|
ofpbuf_uninit(&ofpacts);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return error;
|
2010-10-01 13:05:59 -07:00
|
|
|
|
}
|
|
|
|
|
|
2010-12-07 13:22:46 -08:00
|
|
|
|
ds_put_char(s, ' ');
|
|
|
|
|
switch (fm.command) {
|
2009-07-08 13:19:16 -07:00
|
|
|
|
case OFPFC_ADD:
|
2010-12-07 13:22:46 -08:00
|
|
|
|
ds_put_cstr(s, "ADD");
|
2009-07-08 13:19:16 -07:00
|
|
|
|
break;
|
|
|
|
|
case OFPFC_MODIFY:
|
2010-12-07 13:22:46 -08:00
|
|
|
|
ds_put_cstr(s, "MOD");
|
2009-07-08 13:19:16 -07:00
|
|
|
|
break;
|
|
|
|
|
case OFPFC_MODIFY_STRICT:
|
2010-12-07 13:22:46 -08:00
|
|
|
|
ds_put_cstr(s, "MOD_STRICT");
|
2009-07-08 13:19:16 -07:00
|
|
|
|
break;
|
|
|
|
|
case OFPFC_DELETE:
|
2010-12-07 13:22:46 -08:00
|
|
|
|
ds_put_cstr(s, "DEL");
|
2009-07-08 13:19:16 -07:00
|
|
|
|
break;
|
|
|
|
|
case OFPFC_DELETE_STRICT:
|
2010-12-07 13:22:46 -08:00
|
|
|
|
ds_put_cstr(s, "DEL_STRICT");
|
2009-07-08 13:19:16 -07:00
|
|
|
|
break;
|
|
|
|
|
default:
|
2010-12-07 13:22:46 -08:00
|
|
|
|
ds_put_format(s, "cmd:%d", fm.command);
|
|
|
|
|
}
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
if (fm.table_id != 0
|
|
|
|
|
|| ofputil_table_map_get_name(table_map, fm.table_id)) {
|
|
|
|
|
ds_put_format(s, " table:");
|
|
|
|
|
ofputil_format_table(fm.table_id, table_map, s);
|
2011-05-12 09:58:01 -07:00
|
|
|
|
}
|
2010-12-07 13:22:46 -08:00
|
|
|
|
|
|
|
|
|
ds_put_char(s, ' ');
|
2012-07-19 23:23:17 -07:00
|
|
|
|
ofpraw_decode(&raw, oh);
|
|
|
|
|
if (verbosity >= 3 && raw == OFPRAW_OFPT10_FLOW_MOD) {
|
2012-07-03 23:01:59 -07:00
|
|
|
|
const struct ofp10_flow_mod *ofm = ofpmsg_body(oh);
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ofp10_match_print(s, &ofm->match, port_map, verbosity);
|
2010-12-14 11:36:04 -08:00
|
|
|
|
|
|
|
|
|
/* ofp_print_match() doesn't print priority. */
|
|
|
|
|
need_priority = true;
|
2012-07-19 23:23:17 -07:00
|
|
|
|
} else if (verbosity >= 3 && raw == OFPRAW_NXT_FLOW_MOD) {
|
|
|
|
|
const struct nx_flow_mod *nfm = ofpmsg_body(oh);
|
2010-12-07 13:22:46 -08:00
|
|
|
|
const void *nxm = nfm + 1;
|
2010-12-14 11:36:04 -08:00
|
|
|
|
char *nxm_s;
|
|
|
|
|
|
|
|
|
|
nxm_s = nx_match_to_string(nxm, ntohs(nfm->match_len));
|
2010-12-07 13:22:46 -08:00
|
|
|
|
ds_put_cstr(s, nxm_s);
|
|
|
|
|
free(nxm_s);
|
2010-12-14 11:36:04 -08:00
|
|
|
|
|
|
|
|
|
/* nx_match_to_string() doesn't print priority. */
|
|
|
|
|
need_priority = true;
|
2010-12-07 13:22:46 -08:00
|
|
|
|
} else {
|
2017-05-31 16:06:12 -07:00
|
|
|
|
match_format(&fm.match, port_map, s, fm.priority);
|
2010-12-14 11:36:04 -08:00
|
|
|
|
|
2012-08-07 15:28:18 -07:00
|
|
|
|
/* match_format() does print priority. */
|
2010-12-14 11:36:04 -08:00
|
|
|
|
need_priority = false;
|
2010-10-01 13:05:59 -07:00
|
|
|
|
}
|
2010-12-07 13:22:46 -08:00
|
|
|
|
|
|
|
|
|
if (ds_last(s) != ' ') {
|
|
|
|
|
ds_put_char(s, ' ');
|
2010-10-01 13:05:59 -07:00
|
|
|
|
}
|
2013-06-27 15:27:15 -07:00
|
|
|
|
if (fm.new_cookie != htonll(0) && fm.new_cookie != OVS_BE64_MAX) {
|
2012-03-24 01:02:26 -07:00
|
|
|
|
ds_put_format(s, "cookie:0x%"PRIx64" ", ntohll(fm.new_cookie));
|
|
|
|
|
}
|
|
|
|
|
if (fm.cookie_mask != htonll(0)) {
|
|
|
|
|
ds_put_format(s, "cookie:0x%"PRIx64"/0x%"PRIx64" ",
|
|
|
|
|
ntohll(fm.cookie), ntohll(fm.cookie_mask));
|
2010-10-01 13:05:59 -07:00
|
|
|
|
}
|
2010-12-07 13:22:46 -08:00
|
|
|
|
if (fm.idle_timeout != OFP_FLOW_PERMANENT) {
|
|
|
|
|
ds_put_format(s, "idle:%"PRIu16" ", fm.idle_timeout);
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
2010-12-07 13:22:46 -08:00
|
|
|
|
if (fm.hard_timeout != OFP_FLOW_PERMANENT) {
|
|
|
|
|
ds_put_format(s, "hard:%"PRIu16" ", fm.hard_timeout);
|
2010-10-01 13:05:59 -07:00
|
|
|
|
}
|
2014-11-07 18:18:48 +05:30
|
|
|
|
if (fm.importance != 0) {
|
|
|
|
|
ds_put_format(s, "importance:%"PRIu16" ", fm.importance);
|
|
|
|
|
}
|
2012-08-07 15:28:18 -07:00
|
|
|
|
if (fm.priority != OFP_DEFAULT_PRIORITY && need_priority) {
|
2017-03-17 13:38:55 -07:00
|
|
|
|
ds_put_format(s, "pri:%d ", fm.priority);
|
2010-10-01 13:05:59 -07:00
|
|
|
|
}
|
2010-12-07 13:22:46 -08:00
|
|
|
|
if (fm.buffer_id != UINT32_MAX) {
|
|
|
|
|
ds_put_format(s, "buf:0x%"PRIx32" ", fm.buffer_id);
|
2010-10-01 13:05:59 -07:00
|
|
|
|
}
|
2012-11-26 18:17:08 +02:00
|
|
|
|
if (fm.out_port != OFPP_ANY) {
|
2012-07-06 13:05:38 -07:00
|
|
|
|
ds_put_format(s, "out_port:");
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ofputil_format_port(fm.out_port, port_map, s);
|
2012-07-06 13:05:38 -07:00
|
|
|
|
ds_put_char(s, ' ');
|
|
|
|
|
}
|
2013-08-26 16:23:50 -07:00
|
|
|
|
|
|
|
|
|
if (oh->version == OFP10_VERSION || oh->version == OFP11_VERSION) {
|
|
|
|
|
/* Don't print the reset_counts flag for OF1.0 and OF1.1 because those
|
|
|
|
|
* versions don't really have such a flag and printing one is likely to
|
|
|
|
|
* confuse people. */
|
|
|
|
|
fm.flags &= ~OFPUTIL_FF_RESET_COUNTS;
|
2010-12-07 13:22:46 -08:00
|
|
|
|
}
|
2013-08-26 16:23:50 -07:00
|
|
|
|
ofp_print_flow_flags(s, fm.flags);
|
2010-12-07 13:22:46 -08:00
|
|
|
|
|
2013-10-14 14:08:20 -07:00
|
|
|
|
ds_put_cstr(s, "actions=");
|
2018-01-12 12:56:12 -08:00
|
|
|
|
struct ofpact_format_params fp = {
|
|
|
|
|
.port_map = port_map,
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
.table_map = table_map,
|
2018-01-12 12:56:12 -08:00
|
|
|
|
.s = s,
|
|
|
|
|
};
|
|
|
|
|
ofpacts_format(fm.ofpacts, fm.ofpacts_len, &fp);
|
2012-07-03 22:17:14 -07:00
|
|
|
|
ofpbuf_uninit(&ofpacts);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
|
|
|
|
|
return 0;
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
2010-12-07 15:45:10 -08:00
|
|
|
|
static void
|
|
|
|
|
ofp_print_duration(struct ds *string, unsigned int sec, unsigned int nsec)
|
|
|
|
|
{
|
|
|
|
|
ds_put_format(string, "%u", sec);
|
ofp-print: Print durations with at least three decimals.
Occasionally I run a command like this:
watch -n.1 ovs-ofctl dump-flows br0
to see how flows change over time. Until now, it has been more difficult
than necessary to spot real changes, because flows "jump around" as the
number of decimals printed for duration changes from moment to moment.
That is, you might see
cookie=0x0, duration=4.566s, table=0, n_packets=0, ...
one moment, and then
cookie=0x0, duration=4.8s, table=0, n_packets=0, ...
the next moment. Shortening 4.8 to 4.800 shifts everything following it
two places to the left, creating a visual jump.
This commit avoids that problem by always printing at least three decimals
if we print any. There can still be an occasional jump if a duration is
exactly on a second boundary, but that only happens 1/1000 of the time.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Andy Zhou <azhou@nicira.com>
2013-12-20 08:39:27 -08:00
|
|
|
|
|
|
|
|
|
/* If there are no fractional seconds, don't print any decimals.
|
|
|
|
|
*
|
|
|
|
|
* If the fractional seconds can be expressed exactly as milliseconds,
|
|
|
|
|
* print 3 decimals. Open vSwitch provides millisecond precision for most
|
|
|
|
|
* time measurements, so printing 3 decimals every time makes it easier to
|
|
|
|
|
* spot real changes in flow dumps that refresh themselves quickly.
|
|
|
|
|
*
|
|
|
|
|
* If the fractional seconds are more precise than milliseconds, print the
|
|
|
|
|
* number of decimals needed to express them exactly.
|
|
|
|
|
*/
|
2010-12-07 15:45:10 -08:00
|
|
|
|
if (nsec > 0) {
|
ofp-print: Print durations with at least three decimals.
Occasionally I run a command like this:
watch -n.1 ovs-ofctl dump-flows br0
to see how flows change over time. Until now, it has been more difficult
than necessary to spot real changes, because flows "jump around" as the
number of decimals printed for duration changes from moment to moment.
That is, you might see
cookie=0x0, duration=4.566s, table=0, n_packets=0, ...
one moment, and then
cookie=0x0, duration=4.8s, table=0, n_packets=0, ...
the next moment. Shortening 4.8 to 4.800 shifts everything following it
two places to the left, creating a visual jump.
This commit avoids that problem by always printing at least three decimals
if we print any. There can still be an occasional jump if a duration is
exactly on a second boundary, but that only happens 1/1000 of the time.
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Andy Zhou <azhou@nicira.com>
2013-12-20 08:39:27 -08:00
|
|
|
|
unsigned int msec = nsec / 1000000;
|
|
|
|
|
if (msec * 1000000 == nsec) {
|
|
|
|
|
ds_put_format(string, ".%03u", msec);
|
|
|
|
|
} else {
|
|
|
|
|
ds_put_format(string, ".%09u", nsec);
|
|
|
|
|
while (string->string[string->length - 1] == '0') {
|
|
|
|
|
string->length--;
|
|
|
|
|
}
|
2010-12-07 15:45:10 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ds_put_char(string, 's');
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-12 14:49:19 -07:00
|
|
|
|
/* Returns a string form of 'reason'. The return value is either a statically
|
|
|
|
|
* allocated constant string or the 'bufsize'-byte buffer 'reasonbuf'.
|
|
|
|
|
* 'bufsize' should be at least OFP_FLOW_REMOVED_REASON_BUFSIZE. */
|
|
|
|
|
#define OFP_FLOW_REMOVED_REASON_BUFSIZE (INT_STRLEN(int) + 1)
|
2012-02-09 14:06:35 -08:00
|
|
|
|
static const char *
|
2013-06-12 14:49:19 -07:00
|
|
|
|
ofp_flow_removed_reason_to_string(enum ofp_flow_removed_reason reason,
|
|
|
|
|
char *reasonbuf, size_t bufsize)
|
2012-02-09 14:06:35 -08:00
|
|
|
|
{
|
|
|
|
|
switch (reason) {
|
|
|
|
|
case OFPRR_IDLE_TIMEOUT:
|
|
|
|
|
return "idle";
|
|
|
|
|
case OFPRR_HARD_TIMEOUT:
|
|
|
|
|
return "hard";
|
|
|
|
|
case OFPRR_DELETE:
|
|
|
|
|
return "delete";
|
2012-03-30 11:30:00 +09:00
|
|
|
|
case OFPRR_GROUP_DELETE:
|
|
|
|
|
return "group_delete";
|
2012-07-03 14:23:10 -07:00
|
|
|
|
case OFPRR_EVICTION:
|
|
|
|
|
return "eviction";
|
2013-06-20 17:26:18 +03:00
|
|
|
|
case OFPRR_METER_DELETE:
|
|
|
|
|
return "meter_delete";
|
2015-06-12 16:12:56 -07:00
|
|
|
|
case OVS_OFPRR_NONE:
|
2012-02-09 14:06:35 -08:00
|
|
|
|
default:
|
2013-06-12 14:49:19 -07:00
|
|
|
|
snprintf(reasonbuf, bufsize, "%d", (int) reason);
|
|
|
|
|
return reasonbuf;
|
2012-02-09 14:06:35 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ofp_print_flow_removed(struct ds *string, const struct ofp_header *oh,
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
const struct ofputil_port_map *port_map,
|
|
|
|
|
const struct ofputil_table_map *table_map)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
2013-06-12 14:49:19 -07:00
|
|
|
|
char reasonbuf[OFP_FLOW_REMOVED_REASON_BUFSIZE];
|
2010-12-09 10:31:49 -08:00
|
|
|
|
struct ofputil_flow_removed fr;
|
2012-01-12 15:48:19 -08:00
|
|
|
|
enum ofperr error;
|
2010-12-09 10:31:49 -08:00
|
|
|
|
|
2011-04-26 09:42:18 -07:00
|
|
|
|
error = ofputil_decode_flow_removed(&fr, oh);
|
2010-12-09 10:31:49 -08:00
|
|
|
|
if (error) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return error;
|
2010-12-09 10:31:49 -08:00
|
|
|
|
}
|
|
|
|
|
|
2010-12-13 16:19:19 -08:00
|
|
|
|
ds_put_char(string, ' ');
|
2017-05-31 16:06:12 -07:00
|
|
|
|
match_format(&fr.match, port_map, string, fr.priority);
|
2010-12-09 10:31:49 -08:00
|
|
|
|
|
2012-02-09 14:06:35 -08:00
|
|
|
|
ds_put_format(string, " reason=%s",
|
2013-06-12 14:49:19 -07:00
|
|
|
|
ofp_flow_removed_reason_to_string(fr.reason, reasonbuf,
|
|
|
|
|
sizeof reasonbuf));
|
2010-10-01 13:05:59 -07:00
|
|
|
|
|
2012-10-01 16:51:49 +09:00
|
|
|
|
if (fr.table_id != 255) {
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
ds_put_format(string, " table_id=");
|
|
|
|
|
ofputil_format_table(fr.table_id, table_map, string);
|
2012-10-01 16:51:49 +09:00
|
|
|
|
}
|
|
|
|
|
|
2010-12-09 10:31:49 -08:00
|
|
|
|
if (fr.cookie != htonll(0)) {
|
|
|
|
|
ds_put_format(string, " cookie:0x%"PRIx64, ntohll(fr.cookie));
|
2010-10-01 13:05:59 -07:00
|
|
|
|
}
|
2010-12-07 15:45:10 -08:00
|
|
|
|
ds_put_cstr(string, " duration");
|
2010-12-09 10:31:49 -08:00
|
|
|
|
ofp_print_duration(string, fr.duration_sec, fr.duration_nsec);
|
2012-08-09 11:01:48 -07:00
|
|
|
|
ds_put_format(string, " idle%"PRIu16, fr.idle_timeout);
|
|
|
|
|
if (fr.hard_timeout) {
|
|
|
|
|
/* The hard timeout was only added in OF1.2, so only print it if it is
|
|
|
|
|
* actually in use to avoid gratuitous change to the formatting. */
|
|
|
|
|
ds_put_format(string, " hard%"PRIu16, fr.hard_timeout);
|
|
|
|
|
}
|
|
|
|
|
ds_put_format(string, " pkts%"PRIu64" bytes%"PRIu64"\n",
|
|
|
|
|
fr.packet_count, fr.byte_count);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return 0;
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ofp_print_port_mod(struct ds *string, const struct ofp_header *oh,
|
|
|
|
|
const struct ofputil_port_map *port_map)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
2012-02-15 16:33:04 -08:00
|
|
|
|
struct ofputil_port_mod pm;
|
|
|
|
|
enum ofperr error;
|
|
|
|
|
|
2014-05-09 08:57:31 -07:00
|
|
|
|
error = ofputil_decode_port_mod(oh, &pm, true);
|
2012-02-15 16:33:04 -08:00
|
|
|
|
if (error) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return error;
|
2012-02-15 16:33:04 -08:00
|
|
|
|
}
|
|
|
|
|
|
2015-12-24 15:29:26 -08:00
|
|
|
|
ds_put_cstr(string, " port: ");
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ofputil_format_port(pm.port_no, port_map, string);
|
2013-01-14 14:43:53 +02:00
|
|
|
|
ds_put_format(string, ": addr:"ETH_ADDR_FMT"\n",
|
|
|
|
|
ETH_ADDR_ARGS(pm.hw_addr));
|
2017-04-05 23:08:09 -07:00
|
|
|
|
if (!eth_addr64_is_zero(pm.hw_addr64)) {
|
|
|
|
|
ds_put_format(string, " addr64: "ETH_ADDR64_FMT"\n",
|
|
|
|
|
ETH_ADDR64_ARGS(pm.hw_addr64));
|
|
|
|
|
}
|
2012-02-15 16:33:04 -08:00
|
|
|
|
|
2013-01-14 14:43:53 +02:00
|
|
|
|
ds_put_cstr(string, " config: ");
|
2012-02-15 16:33:04 -08:00
|
|
|
|
ofp_print_port_config(string, pm.config);
|
|
|
|
|
|
2013-01-14 14:43:53 +02:00
|
|
|
|
ds_put_cstr(string, " mask: ");
|
2012-02-15 16:33:04 -08:00
|
|
|
|
ofp_print_port_config(string, pm.mask);
|
|
|
|
|
|
2013-01-14 14:43:53 +02:00
|
|
|
|
ds_put_cstr(string, " advertise: ");
|
2012-02-15 16:33:04 -08:00
|
|
|
|
if (pm.advertise) {
|
|
|
|
|
ofp_print_port_features(string, pm.advertise);
|
2009-07-08 13:19:16 -07:00
|
|
|
|
} else {
|
2013-01-14 14:43:53 +02:00
|
|
|
|
ds_put_cstr(string, "UNCHANGED\n");
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
2018-01-04 22:40:01 -08:00
|
|
|
|
|
|
|
|
|
return 0;
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
2015-07-02 20:33:08 -07:00
|
|
|
|
static const char *
|
|
|
|
|
ofputil_table_miss_to_string(enum ofputil_table_miss miss)
|
2013-09-07 03:02:32 -07:00
|
|
|
|
{
|
2014-08-11 11:31:45 -07:00
|
|
|
|
switch (miss) {
|
2015-07-02 20:33:08 -07:00
|
|
|
|
case OFPUTIL_TABLE_MISS_DEFAULT: return "default";
|
|
|
|
|
case OFPUTIL_TABLE_MISS_CONTROLLER: return "controller";
|
|
|
|
|
case OFPUTIL_TABLE_MISS_CONTINUE: return "continue";
|
|
|
|
|
case OFPUTIL_TABLE_MISS_DROP: return "drop";
|
|
|
|
|
default: return "***error***";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
|
ofputil_table_eviction_to_string(enum ofputil_table_eviction eviction)
|
|
|
|
|
{
|
|
|
|
|
switch (eviction) {
|
|
|
|
|
case OFPUTIL_TABLE_EVICTION_DEFAULT: return "default";
|
|
|
|
|
case OFPUTIL_TABLE_EVICTION_ON: return "on";
|
|
|
|
|
case OFPUTIL_TABLE_EVICTION_OFF: return "off";
|
|
|
|
|
default: return "***error***";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
|
ofputil_eviction_flag_to_string(uint32_t bit)
|
|
|
|
|
{
|
|
|
|
|
enum ofp14_table_mod_prop_eviction_flag eviction_flag = bit;
|
|
|
|
|
|
|
|
|
|
switch (eviction_flag) {
|
|
|
|
|
case OFPTMPEF14_OTHER: return "OTHER";
|
|
|
|
|
case OFPTMPEF14_IMPORTANCE: return "IMPORTANCE";
|
|
|
|
|
case OFPTMPEF14_LIFETIME: return "LIFETIME";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Appends to 'string' a description of the bitmap of OFPTMPEF14_* values in
|
|
|
|
|
* 'eviction_flags'. */
|
|
|
|
|
static void
|
|
|
|
|
ofputil_put_eviction_flags(struct ds *string, uint32_t eviction_flags)
|
|
|
|
|
{
|
|
|
|
|
if (eviction_flags != UINT32_MAX) {
|
|
|
|
|
ofp_print_bit_names(string, eviction_flags,
|
|
|
|
|
ofputil_eviction_flag_to_string, '|');
|
|
|
|
|
} else {
|
|
|
|
|
ds_put_cstr(string, "(default)");
|
2013-09-07 03:02:32 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-24 17:49:42 +05:30
|
|
|
|
static const char *
|
|
|
|
|
ofputil_table_vacancy_to_string(enum ofputil_table_vacancy vacancy)
|
|
|
|
|
{
|
|
|
|
|
switch (vacancy) {
|
|
|
|
|
case OFPUTIL_TABLE_VACANCY_DEFAULT: return "default";
|
|
|
|
|
case OFPUTIL_TABLE_VACANCY_ON: return "on";
|
|
|
|
|
case OFPUTIL_TABLE_VACANCY_OFF: return "off";
|
|
|
|
|
default: return "***error***";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
ofp_print_table_mod(struct ds *string, const struct ofp_header *oh,
|
|
|
|
|
const struct ofputil_table_map *table_map)
|
2013-09-07 03:02:32 -07:00
|
|
|
|
{
|
|
|
|
|
struct ofputil_table_mod pm;
|
|
|
|
|
enum ofperr error;
|
|
|
|
|
|
|
|
|
|
error = ofputil_decode_table_mod(oh, &pm);
|
|
|
|
|
if (error) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return error;
|
2013-09-07 03:02:32 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (pm.table_id == 0xff) {
|
|
|
|
|
ds_put_cstr(string, " table_id: ALL_TABLES");
|
|
|
|
|
} else {
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
ds_put_format(string, " table_id=");
|
|
|
|
|
ofputil_format_table(pm.table_id, table_map, string);
|
2013-09-07 03:02:32 -07:00
|
|
|
|
}
|
|
|
|
|
|
2015-07-02 20:33:08 -07:00
|
|
|
|
if (pm.miss != OFPUTIL_TABLE_MISS_DEFAULT) {
|
|
|
|
|
ds_put_format(string, ", flow_miss_config=%s",
|
|
|
|
|
ofputil_table_miss_to_string(pm.miss));
|
|
|
|
|
}
|
|
|
|
|
if (pm.eviction != OFPUTIL_TABLE_EVICTION_DEFAULT) {
|
|
|
|
|
ds_put_format(string, ", eviction=%s",
|
|
|
|
|
ofputil_table_eviction_to_string(pm.eviction));
|
|
|
|
|
}
|
|
|
|
|
if (pm.eviction_flags != UINT32_MAX) {
|
|
|
|
|
ds_put_cstr(string, "eviction_flags=");
|
|
|
|
|
ofputil_put_eviction_flags(string, pm.eviction_flags);
|
2014-08-11 11:31:45 -07:00
|
|
|
|
}
|
2015-11-24 17:49:42 +05:30
|
|
|
|
if (pm.vacancy != OFPUTIL_TABLE_VACANCY_DEFAULT) {
|
|
|
|
|
ds_put_format(string, ", vacancy=%s",
|
|
|
|
|
ofputil_table_vacancy_to_string(pm.vacancy));
|
|
|
|
|
if (pm.vacancy == OFPUTIL_TABLE_VACANCY_ON) {
|
|
|
|
|
ds_put_format(string, " vacancy:%"PRIu8""
|
|
|
|
|
",%"PRIu8"", pm.table_vacancy.vacancy_down,
|
|
|
|
|
pm.table_vacancy.vacancy_up);
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-01-04 22:40:01 -08:00
|
|
|
|
|
|
|
|
|
return 0;
|
2013-09-07 03:02:32 -07:00
|
|
|
|
}
|
|
|
|
|
|
2015-07-02 20:35:44 -07:00
|
|
|
|
/* This function will print the Table description properties. */
|
|
|
|
|
static void
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
ofp_print_table_desc(struct ds *string, const struct ofputil_table_desc *td,
|
|
|
|
|
const struct ofputil_table_map *table_map)
|
2015-07-02 20:35:44 -07:00
|
|
|
|
{
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
ds_put_format(string, "\n table ");
|
|
|
|
|
ofputil_format_table(td->table_id, table_map, string);
|
2015-07-02 20:35:44 -07:00
|
|
|
|
ds_put_cstr(string, ":\n");
|
|
|
|
|
ds_put_format(string, " eviction=%s eviction_flags=",
|
|
|
|
|
ofputil_table_eviction_to_string(td->eviction));
|
|
|
|
|
ofputil_put_eviction_flags(string, td->eviction_flags);
|
|
|
|
|
ds_put_char(string, '\n');
|
2015-11-24 17:50:22 +05:30
|
|
|
|
ds_put_format(string, " vacancy=%s",
|
|
|
|
|
ofputil_table_vacancy_to_string(td->vacancy));
|
|
|
|
|
if (td->vacancy == OFPUTIL_TABLE_VACANCY_ON) {
|
|
|
|
|
ds_put_format(string, " vacancy_down=%"PRIu8"%%",
|
|
|
|
|
td->table_vacancy.vacancy_down);
|
|
|
|
|
ds_put_format(string, " vacancy_up=%"PRIu8"%%",
|
|
|
|
|
td->table_vacancy.vacancy_up);
|
|
|
|
|
ds_put_format(string, " vacancy=%"PRIu8"%%",
|
|
|
|
|
td->table_vacancy.vacancy);
|
|
|
|
|
}
|
|
|
|
|
ds_put_char(string, '\n');
|
2015-07-02 20:35:44 -07:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
ofp_print_table_status_message(struct ds *string, const struct ofp_header *oh,
|
|
|
|
|
const struct ofputil_table_map *table_map)
|
2016-02-18 15:54:26 +05:30
|
|
|
|
{
|
|
|
|
|
struct ofputil_table_status ts;
|
|
|
|
|
enum ofperr error;
|
|
|
|
|
|
|
|
|
|
error = ofputil_decode_table_status(oh, &ts);
|
|
|
|
|
if (error) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return error;
|
2016-02-18 15:54:26 +05:30
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ts.reason == OFPTR_VACANCY_DOWN) {
|
|
|
|
|
ds_put_format(string, " reason=VACANCY_DOWN");
|
|
|
|
|
} else if (ts.reason == OFPTR_VACANCY_UP) {
|
|
|
|
|
ds_put_format(string, " reason=VACANCY_UP");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ds_put_format(string, "\ntable_desc:-");
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
ofp_print_table_desc(string, &ts.desc, table_map);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
|
|
|
|
|
return 0;
|
2016-02-18 15:54:26 +05:30
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2013-10-24 15:54:03 -07:00
|
|
|
|
ofp_print_queue_get_config_request(struct ds *string,
|
2017-05-31 16:06:12 -07:00
|
|
|
|
const struct ofp_header *oh,
|
|
|
|
|
const struct ofputil_port_map *port_map)
|
2013-10-24 15:54:03 -07:00
|
|
|
|
{
|
|
|
|
|
enum ofperr error;
|
|
|
|
|
ofp_port_t port;
|
2016-01-18 16:00:05 -08:00
|
|
|
|
uint32_t queue;
|
2013-10-24 15:54:03 -07:00
|
|
|
|
|
2016-01-18 16:00:05 -08:00
|
|
|
|
error = ofputil_decode_queue_get_config_request(oh, &port, &queue);
|
2013-10-24 15:54:03 -07:00
|
|
|
|
if (error) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return error;
|
2013-10-24 15:54:03 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ds_put_cstr(string, " port=");
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ofputil_format_port(port, port_map, string);
|
2016-01-18 16:00:05 -08:00
|
|
|
|
|
|
|
|
|
if (queue != OFPQ_ALL) {
|
|
|
|
|
ds_put_cstr(string, " queue=");
|
|
|
|
|
ofp_print_queue_name(string, queue);
|
|
|
|
|
}
|
2018-01-04 22:40:01 -08:00
|
|
|
|
|
|
|
|
|
return 0;
|
2013-10-24 15:54:03 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
print_queue_rate(struct ds *string, const char *name, unsigned int rate)
|
|
|
|
|
{
|
|
|
|
|
if (rate <= 1000) {
|
|
|
|
|
ds_put_format(string, " %s:%u.%u%%", name, rate / 10, rate % 10);
|
|
|
|
|
} else if (rate < UINT16_MAX) {
|
|
|
|
|
ds_put_format(string, " %s:(disabled)", name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-26 15:14:54 -07:00
|
|
|
|
/* qsort comparison function. */
|
|
|
|
|
static int
|
|
|
|
|
compare_queues(const void *a_, const void *b_)
|
|
|
|
|
{
|
|
|
|
|
const struct ofputil_queue_config *a = a_;
|
|
|
|
|
const struct ofputil_queue_config *b = b_;
|
|
|
|
|
|
|
|
|
|
uint16_t ap = ofp_to_u16(a->port);
|
|
|
|
|
uint16_t bp = ofp_to_u16(b->port);
|
|
|
|
|
if (ap != bp) {
|
|
|
|
|
return ap < bp ? -1 : 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t aq = a->queue;
|
|
|
|
|
uint32_t bq = b->queue;
|
|
|
|
|
return aq < bq ? -1 : aq > bq;
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2013-10-24 15:54:03 -07:00
|
|
|
|
ofp_print_queue_get_config_reply(struct ds *string,
|
2017-05-31 16:06:12 -07:00
|
|
|
|
const struct ofp_header *oh,
|
|
|
|
|
const struct ofputil_port_map *port_map)
|
2013-10-24 15:54:03 -07:00
|
|
|
|
{
|
2016-02-18 15:13:09 -08:00
|
|
|
|
struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
|
2013-10-24 15:54:03 -07:00
|
|
|
|
|
2016-05-26 15:14:54 -07:00
|
|
|
|
struct ofputil_queue_config *queues = NULL;
|
|
|
|
|
size_t allocated_queues = 0;
|
|
|
|
|
size_t n = 0;
|
2013-10-24 15:54:03 -07:00
|
|
|
|
|
2016-05-26 15:14:54 -07:00
|
|
|
|
int retval = 0;
|
|
|
|
|
for (;;) {
|
|
|
|
|
if (n >= allocated_queues) {
|
|
|
|
|
queues = x2nrealloc(queues, &allocated_queues, sizeof *queues);
|
|
|
|
|
}
|
|
|
|
|
retval = ofputil_pull_queue_get_config_reply(&b, &queues[n]);
|
2013-10-24 15:54:03 -07:00
|
|
|
|
if (retval) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
2016-05-26 15:14:54 -07:00
|
|
|
|
n++;
|
|
|
|
|
}
|
2013-10-24 15:54:03 -07:00
|
|
|
|
|
2016-05-26 15:14:54 -07:00
|
|
|
|
qsort(queues, n, sizeof *queues, compare_queues);
|
|
|
|
|
|
|
|
|
|
ds_put_char(string, ' ');
|
|
|
|
|
|
|
|
|
|
ofp_port_t port = 0;
|
|
|
|
|
for (const struct ofputil_queue_config *q = queues; q < &queues[n]; q++) {
|
|
|
|
|
if (q->port != port) {
|
|
|
|
|
port = q->port;
|
2016-01-18 16:00:05 -08:00
|
|
|
|
|
|
|
|
|
ds_put_cstr(string, "port=");
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ofputil_format_port(port, port_map, string);
|
2016-01-18 16:00:05 -08:00
|
|
|
|
ds_put_char(string, '\n');
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-26 15:14:54 -07:00
|
|
|
|
ds_put_format(string, "queue %"PRIu32":", q->queue);
|
|
|
|
|
print_queue_rate(string, "min_rate", q->min_rate);
|
|
|
|
|
print_queue_rate(string, "max_rate", q->max_rate);
|
2013-10-24 15:54:03 -07:00
|
|
|
|
ds_put_char(string, '\n');
|
|
|
|
|
}
|
2016-05-26 15:14:54 -07:00
|
|
|
|
|
|
|
|
|
ds_chomp(string, ' ');
|
2016-11-21 13:42:40 -08:00
|
|
|
|
free(queues);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
|
|
|
|
|
return retval != EOF ? retval : 0;
|
2013-10-24 15:54:03 -07:00
|
|
|
|
}
|
|
|
|
|
|
2013-06-20 17:26:18 +03:00
|
|
|
|
static void
|
|
|
|
|
ofp_print_meter_flags(struct ds *s, uint16_t flags)
|
|
|
|
|
{
|
|
|
|
|
if (flags & OFPMF13_KBPS) {
|
|
|
|
|
ds_put_cstr(s, "kbps ");
|
|
|
|
|
}
|
|
|
|
|
if (flags & OFPMF13_PKTPS) {
|
|
|
|
|
ds_put_cstr(s, "pktps ");
|
|
|
|
|
}
|
|
|
|
|
if (flags & OFPMF13_BURST) {
|
|
|
|
|
ds_put_cstr(s, "burst ");
|
|
|
|
|
}
|
|
|
|
|
if (flags & OFPMF13_STATS) {
|
|
|
|
|
ds_put_cstr(s, "stats ");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
flags &= ~(OFPMF13_KBPS | OFPMF13_PKTPS | OFPMF13_BURST | OFPMF13_STATS);
|
|
|
|
|
if (flags) {
|
|
|
|
|
ds_put_format(s, "flags:0x%"PRIx16" ", flags);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
ofp_print_meter_band(struct ds *s, uint16_t flags,
|
|
|
|
|
const struct ofputil_meter_band *mb)
|
|
|
|
|
{
|
|
|
|
|
ds_put_cstr(s, "\ntype=");
|
|
|
|
|
switch (mb->type) {
|
|
|
|
|
case OFPMBT13_DROP:
|
|
|
|
|
ds_put_cstr(s, "drop");
|
|
|
|
|
break;
|
|
|
|
|
case OFPMBT13_DSCP_REMARK:
|
|
|
|
|
ds_put_cstr(s, "dscp_remark");
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
ds_put_format(s, "%u", mb->type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ds_put_format(s, " rate=%"PRIu32, mb->rate);
|
|
|
|
|
|
|
|
|
|
if (flags & OFPMF13_BURST) {
|
|
|
|
|
ds_put_format(s, " burst_size=%"PRIu32, mb->burst_size);
|
|
|
|
|
}
|
|
|
|
|
if (mb->type == OFPMBT13_DSCP_REMARK) {
|
|
|
|
|
ds_put_format(s, " prec_level=%"PRIu8, mb->prec_level);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-05 16:16:12 -07:00
|
|
|
|
static void
|
|
|
|
|
ofp_print_meter_id(struct ds *s, uint32_t meter_id, char seperator)
|
|
|
|
|
{
|
|
|
|
|
if (meter_id <= OFPM13_MAX) {
|
|
|
|
|
ds_put_format(s, "meter%c%"PRIu32, seperator, meter_id);
|
|
|
|
|
} else {
|
|
|
|
|
const char *name;
|
|
|
|
|
switch (meter_id) {
|
|
|
|
|
case OFPM13_SLOWPATH:
|
|
|
|
|
name = "slowpath";
|
|
|
|
|
break;
|
|
|
|
|
case OFPM13_CONTROLLER:
|
|
|
|
|
name = "controller";
|
|
|
|
|
break;
|
|
|
|
|
case OFPM13_ALL:
|
|
|
|
|
name = "all";
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
name = "unknown";
|
|
|
|
|
}
|
|
|
|
|
ds_put_format(s, "meter%c%s", seperator, name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-20 17:26:18 +03:00
|
|
|
|
static void
|
|
|
|
|
ofp_print_meter_stats(struct ds *s, const struct ofputil_meter_stats *ms)
|
|
|
|
|
{
|
|
|
|
|
uint16_t i;
|
|
|
|
|
|
2017-04-05 16:16:12 -07:00
|
|
|
|
ofp_print_meter_id(s, ms->meter_id, ':');
|
|
|
|
|
ds_put_char(s, ' ');
|
2013-06-20 17:26:18 +03:00
|
|
|
|
ds_put_format(s, "flow_count:%"PRIu32" ", ms->flow_count);
|
|
|
|
|
ds_put_format(s, "packet_in_count:%"PRIu64" ", ms->packet_in_count);
|
|
|
|
|
ds_put_format(s, "byte_in_count:%"PRIu64" ", ms->byte_in_count);
|
|
|
|
|
ds_put_cstr(s, "duration:");
|
|
|
|
|
ofp_print_duration(s, ms->duration_sec, ms->duration_nsec);
|
|
|
|
|
ds_put_char(s, ' ');
|
|
|
|
|
|
|
|
|
|
ds_put_cstr(s, "bands:\n");
|
|
|
|
|
for (i = 0; i < ms->n_bands; ++i) {
|
|
|
|
|
ds_put_format(s, "%d: ", i);
|
|
|
|
|
ds_put_format(s, "packet_count:%"PRIu64" ", ms->bands[i].packet_count);
|
|
|
|
|
ds_put_format(s, "byte_count:%"PRIu64"\n", ms->bands[i].byte_count);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
ofp_print_meter_config(struct ds *s, const struct ofputil_meter_config *mc)
|
|
|
|
|
{
|
|
|
|
|
uint16_t i;
|
|
|
|
|
|
2017-04-05 16:16:12 -07:00
|
|
|
|
ofp_print_meter_id(s, mc->meter_id, '=');
|
|
|
|
|
ds_put_char(s, ' ');
|
2013-06-20 17:26:18 +03:00
|
|
|
|
|
|
|
|
|
ofp_print_meter_flags(s, mc->flags);
|
|
|
|
|
|
|
|
|
|
ds_put_cstr(s, "bands=");
|
|
|
|
|
for (i = 0; i < mc->n_bands; ++i) {
|
|
|
|
|
ofp_print_meter_band(s, mc->flags, &mc->bands[i]);
|
|
|
|
|
}
|
|
|
|
|
ds_put_char(s, '\n');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-09-09 17:33:42 +05:30
|
|
|
|
ofp_print_meter_mod__(struct ds *s, const struct ofputil_meter_mod *mm)
|
2013-06-20 17:26:18 +03:00
|
|
|
|
{
|
2015-09-09 17:33:42 +05:30
|
|
|
|
switch (mm->command) {
|
2013-06-20 17:26:18 +03:00
|
|
|
|
case OFPMC13_ADD:
|
|
|
|
|
ds_put_cstr(s, " ADD ");
|
|
|
|
|
break;
|
|
|
|
|
case OFPMC13_MODIFY:
|
|
|
|
|
ds_put_cstr(s, " MOD ");
|
|
|
|
|
break;
|
|
|
|
|
case OFPMC13_DELETE:
|
|
|
|
|
ds_put_cstr(s, " DEL ");
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2015-09-09 17:33:42 +05:30
|
|
|
|
ds_put_format(s, " cmd:%d ", mm->command);
|
2013-06-20 17:26:18 +03:00
|
|
|
|
}
|
|
|
|
|
|
2015-09-09 17:33:42 +05:30
|
|
|
|
ofp_print_meter_config(s, &mm->meter);
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2015-09-09 17:33:42 +05:30
|
|
|
|
ofp_print_meter_mod(struct ds *s, const struct ofp_header *oh)
|
|
|
|
|
{
|
|
|
|
|
struct ofputil_meter_mod mm;
|
|
|
|
|
struct ofpbuf bands;
|
|
|
|
|
enum ofperr error;
|
|
|
|
|
|
|
|
|
|
ofpbuf_init(&bands, 64);
|
|
|
|
|
error = ofputil_decode_meter_mod(oh, &mm, &bands);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
if (!error) {
|
2015-09-09 17:33:42 +05:30
|
|
|
|
ofp_print_meter_mod__(s, &mm);
|
|
|
|
|
}
|
2013-06-20 17:26:18 +03:00
|
|
|
|
ofpbuf_uninit(&bands);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
|
|
|
|
|
return error;
|
2013-06-20 17:26:18 +03:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2013-06-20 17:26:18 +03:00
|
|
|
|
ofp_print_meter_stats_request(struct ds *s, const struct ofp_header *oh)
|
|
|
|
|
{
|
|
|
|
|
uint32_t meter_id;
|
|
|
|
|
|
|
|
|
|
ofputil_decode_meter_request(oh, &meter_id);
|
2017-04-05 16:16:12 -07:00
|
|
|
|
ds_put_char(s, ' ');
|
2013-06-20 17:26:18 +03:00
|
|
|
|
|
2017-04-05 16:16:12 -07:00
|
|
|
|
ofp_print_meter_id(s, meter_id, '=');
|
2018-01-04 22:40:01 -08:00
|
|
|
|
|
|
|
|
|
return 0;
|
2013-06-20 17:26:18 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
|
ofputil_meter_capabilities_to_name(uint32_t bit)
|
|
|
|
|
{
|
|
|
|
|
enum ofp13_meter_flags flag = bit;
|
|
|
|
|
|
|
|
|
|
switch (flag) {
|
|
|
|
|
case OFPMF13_KBPS: return "kbps";
|
|
|
|
|
case OFPMF13_PKTPS: return "pktps";
|
|
|
|
|
case OFPMF13_BURST: return "burst";
|
|
|
|
|
case OFPMF13_STATS: return "stats";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
|
ofputil_meter_band_types_to_name(uint32_t bit)
|
|
|
|
|
{
|
|
|
|
|
switch (bit) {
|
2013-08-21 13:05:36 -07:00
|
|
|
|
case 1 << OFPMBT13_DROP: return "drop";
|
|
|
|
|
case 1 << OFPMBT13_DSCP_REMARK: return "dscp_remark";
|
2013-06-20 17:26:18 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2013-06-20 17:26:18 +03:00
|
|
|
|
ofp_print_meter_features_reply(struct ds *s, const struct ofp_header *oh)
|
|
|
|
|
{
|
|
|
|
|
struct ofputil_meter_features mf;
|
|
|
|
|
|
|
|
|
|
ofputil_decode_meter_features(oh, &mf);
|
|
|
|
|
|
|
|
|
|
ds_put_format(s, "\nmax_meter:%"PRIu32, mf.max_meters);
|
|
|
|
|
ds_put_format(s, " max_bands:%"PRIu8, mf.max_bands);
|
|
|
|
|
ds_put_format(s, " max_color:%"PRIu8"\n", mf.max_color);
|
|
|
|
|
|
|
|
|
|
ds_put_cstr(s, "band_types: ");
|
|
|
|
|
ofp_print_bit_names(s, mf.band_types,
|
|
|
|
|
ofputil_meter_band_types_to_name, ' ');
|
|
|
|
|
ds_put_char(s, '\n');
|
|
|
|
|
|
|
|
|
|
ds_put_cstr(s, "capabilities: ");
|
|
|
|
|
ofp_print_bit_names(s, mf.capabilities,
|
|
|
|
|
ofputil_meter_capabilities_to_name, ' ');
|
|
|
|
|
ds_put_char(s, '\n');
|
2018-01-04 22:40:01 -08:00
|
|
|
|
|
|
|
|
|
return 0;
|
2013-06-20 17:26:18 +03:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2013-06-20 17:26:18 +03:00
|
|
|
|
ofp_print_meter_config_reply(struct ds *s, const struct ofp_header *oh)
|
|
|
|
|
{
|
2016-02-18 15:13:09 -08:00
|
|
|
|
struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
|
2013-06-20 17:26:18 +03:00
|
|
|
|
struct ofpbuf bands;
|
2018-01-04 22:40:01 -08:00
|
|
|
|
int retval;
|
2013-06-20 17:26:18 +03:00
|
|
|
|
|
|
|
|
|
ofpbuf_init(&bands, 64);
|
|
|
|
|
for (;;) {
|
|
|
|
|
struct ofputil_meter_config mc;
|
|
|
|
|
|
|
|
|
|
retval = ofputil_decode_meter_config(&b, &mc, &bands);
|
|
|
|
|
if (retval) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
ds_put_char(s, '\n');
|
|
|
|
|
ofp_print_meter_config(s, &mc);
|
|
|
|
|
}
|
|
|
|
|
ofpbuf_uninit(&bands);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
|
|
|
|
|
return retval != EOF ? retval : 0;
|
2013-06-20 17:26:18 +03:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2013-06-20 17:26:18 +03:00
|
|
|
|
ofp_print_meter_stats_reply(struct ds *s, const struct ofp_header *oh)
|
|
|
|
|
{
|
2016-02-18 15:13:09 -08:00
|
|
|
|
struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
|
2013-06-20 17:26:18 +03:00
|
|
|
|
struct ofpbuf bands;
|
2018-01-04 22:40:01 -08:00
|
|
|
|
int retval;
|
2013-06-20 17:26:18 +03:00
|
|
|
|
|
|
|
|
|
ofpbuf_init(&bands, 64);
|
|
|
|
|
for (;;) {
|
|
|
|
|
struct ofputil_meter_stats ms;
|
|
|
|
|
|
|
|
|
|
retval = ofputil_decode_meter_stats(&b, &ms, &bands);
|
|
|
|
|
if (retval) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
ds_put_char(s, '\n');
|
|
|
|
|
ofp_print_meter_stats(s, &ms);
|
|
|
|
|
}
|
|
|
|
|
ofpbuf_uninit(&bands);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
|
|
|
|
|
return retval != EOF ? retval : 0;
|
2013-06-20 17:26:18 +03:00
|
|
|
|
}
|
|
|
|
|
|
2010-12-07 13:22:46 -08:00
|
|
|
|
static void
|
2012-01-12 15:48:19 -08:00
|
|
|
|
ofp_print_error(struct ds *string, enum ofperr error)
|
2010-12-07 13:22:46 -08:00
|
|
|
|
{
|
2012-01-12 15:48:19 -08:00
|
|
|
|
ds_put_format(string, "***decode error: %s***\n", ofperr_get_name(error));
|
2010-12-07 21:57:09 -08:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2012-11-04 22:04:55 -08:00
|
|
|
|
ofp_print_hello(struct ds *string, const struct ofp_header *oh)
|
|
|
|
|
{
|
|
|
|
|
uint32_t allowed_versions;
|
|
|
|
|
bool ok;
|
|
|
|
|
|
|
|
|
|
ok = ofputil_decode_hello(oh, &allowed_versions);
|
|
|
|
|
|
|
|
|
|
ds_put_cstr(string, "\n version bitmap: ");
|
|
|
|
|
ofputil_format_version_bitmap(string, allowed_versions);
|
|
|
|
|
|
|
|
|
|
if (!ok) {
|
|
|
|
|
ds_put_cstr(string, "\n unknown data in hello:\n");
|
|
|
|
|
ds_put_hex_dump(string, oh, ntohs(oh->length), 0, true);
|
|
|
|
|
}
|
2018-01-04 22:40:01 -08:00
|
|
|
|
|
|
|
|
|
return 0;
|
2012-11-04 22:04:55 -08:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ofp_print_error_msg(struct ds *string, const struct ofp_header *oh,
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
const struct ofputil_port_map *port_map,
|
|
|
|
|
const struct ofputil_table_map *table_map)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
2012-07-19 23:23:17 -07:00
|
|
|
|
struct ofpbuf payload;
|
2012-01-12 15:48:19 -08:00
|
|
|
|
enum ofperr error;
|
2009-07-08 13:19:16 -07:00
|
|
|
|
char *s;
|
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
error = ofperr_decode_msg(oh, &payload);
|
2012-01-12 15:48:19 -08:00
|
|
|
|
if (!error) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return OFPERR_OFPBRC_BAD_LEN;
|
2010-12-07 21:57:09 -08:00
|
|
|
|
}
|
|
|
|
|
|
2012-01-12 15:48:19 -08:00
|
|
|
|
ds_put_format(string, " %s\n", ofperr_get_name(error));
|
2009-07-08 13:19:16 -07:00
|
|
|
|
|
2012-01-12 15:48:19 -08:00
|
|
|
|
if (error == OFPERR_OFPHFC_INCOMPATIBLE || error == OFPERR_OFPHFC_EPERM) {
|
2015-03-02 17:29:44 -08:00
|
|
|
|
ds_put_printable(string, payload.data, payload.size);
|
2012-01-12 15:48:19 -08:00
|
|
|
|
} else {
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
s = ofp_to_string(payload.data, payload.size, port_map, table_map, 1);
|
2009-07-08 13:19:16 -07:00
|
|
|
|
ds_put_cstr(string, s);
|
|
|
|
|
free(s);
|
|
|
|
|
}
|
2014-04-04 19:26:22 -07:00
|
|
|
|
ofpbuf_uninit(&payload);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
|
|
|
|
|
return 0;
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2012-07-19 23:23:17 -07:00
|
|
|
|
ofp_print_port_status(struct ds *string, const struct ofp_header *oh)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
2012-02-15 16:33:04 -08:00
|
|
|
|
struct ofputil_port_status ps;
|
|
|
|
|
enum ofperr error;
|
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
error = ofputil_decode_port_status(oh, &ps);
|
2012-02-15 16:33:04 -08:00
|
|
|
|
if (error) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return error;
|
2012-02-15 16:33:04 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ps.reason == OFPPR_ADD) {
|
2009-07-08 13:19:16 -07:00
|
|
|
|
ds_put_format(string, " ADD:");
|
2012-02-15 16:33:04 -08:00
|
|
|
|
} else if (ps.reason == OFPPR_DELETE) {
|
2009-07-08 13:19:16 -07:00
|
|
|
|
ds_put_format(string, " DEL:");
|
2012-02-15 16:33:04 -08:00
|
|
|
|
} else if (ps.reason == OFPPR_MODIFY) {
|
2009-07-08 13:19:16 -07:00
|
|
|
|
ds_put_format(string, " MOD:");
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-15 16:33:04 -08:00
|
|
|
|
ofp_print_phy_port(string, &ps.desc);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return 0;
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2012-07-19 23:23:17 -07:00
|
|
|
|
ofp_print_ofpst_desc_reply(struct ds *string, const struct ofp_header *oh)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
2012-07-19 23:23:17 -07:00
|
|
|
|
const struct ofp_desc_stats *ods = ofpmsg_body(oh);
|
|
|
|
|
|
2010-12-13 16:19:19 -08:00
|
|
|
|
ds_put_char(string, '\n');
|
2010-08-30 00:24:53 -07:00
|
|
|
|
ds_put_format(string, "Manufacturer: %.*s\n",
|
2010-01-22 15:12:34 -08:00
|
|
|
|
(int) sizeof ods->mfr_desc, ods->mfr_desc);
|
|
|
|
|
ds_put_format(string, "Hardware: %.*s\n",
|
|
|
|
|
(int) sizeof ods->hw_desc, ods->hw_desc);
|
|
|
|
|
ds_put_format(string, "Software: %.*s\n",
|
|
|
|
|
(int) sizeof ods->sw_desc, ods->sw_desc);
|
|
|
|
|
ds_put_format(string, "Serial Num: %.*s\n",
|
|
|
|
|
(int) sizeof ods->serial_num, ods->serial_num);
|
|
|
|
|
ds_put_format(string, "DP Description: %.*s\n",
|
|
|
|
|
(int) sizeof ods->dp_desc, ods->dp_desc);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
|
|
|
|
|
return 0;
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ofp_print_flow_stats_request(struct ds *string, const struct ofp_header *oh,
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
const struct ofputil_port_map *port_map,
|
|
|
|
|
const struct ofputil_table_map *table_map)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
2011-08-08 14:48:48 -07:00
|
|
|
|
struct ofputil_flow_stats_request fsr;
|
2012-01-12 15:48:19 -08:00
|
|
|
|
enum ofperr error;
|
2009-07-08 13:19:16 -07:00
|
|
|
|
|
2017-03-13 11:28:20 -07:00
|
|
|
|
error = ofputil_decode_flow_stats_request(&fsr, oh, NULL, NULL);
|
2010-12-07 14:52:26 -08:00
|
|
|
|
if (error) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return error;
|
2010-12-07 14:52:26 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (fsr.table_id != 0xff) {
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
ds_put_format(string, " table=");
|
|
|
|
|
ofputil_format_table(fsr.table_id, table_map, string);
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
2012-11-26 18:17:08 +02:00
|
|
|
|
if (fsr.out_port != OFPP_ANY) {
|
2010-12-07 14:52:26 -08:00
|
|
|
|
ds_put_cstr(string, " out_port=");
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ofputil_format_port(fsr.out_port, port_map, string);
|
2010-12-07 14:52:26 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ds_put_char(string, ' ');
|
2017-05-31 16:06:12 -07:00
|
|
|
|
match_format(&fsr.match, port_map, string, OFP_DEFAULT_PRIORITY);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
|
|
|
|
|
return 0;
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
2017-06-13 17:09:05 -07:00
|
|
|
|
/* Appends a textual form of 'fs' to 'string', translating port numbers to
|
|
|
|
|
* names using 'port_map' (if provided). If 'show_stats' is true, the output
|
|
|
|
|
* includes the flow duration, packet and byte counts, and its idle and hard
|
|
|
|
|
* ages, otherwise they are omitted. */
|
2012-07-12 13:32:47 -07:00
|
|
|
|
void
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ofp_print_flow_stats(struct ds *string, const struct ofputil_flow_stats *fs,
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
const struct ofputil_port_map *port_map,
|
|
|
|
|
const struct ofputil_table_map *table_map,
|
|
|
|
|
bool show_stats)
|
2017-06-13 17:09:05 -07:00
|
|
|
|
{
|
|
|
|
|
if (show_stats || fs->cookie) {
|
|
|
|
|
ds_put_format(string, "%scookie=%s0x%"PRIx64", ",
|
|
|
|
|
colors.param, colors.end, ntohll(fs->cookie));
|
|
|
|
|
}
|
|
|
|
|
if (show_stats) {
|
|
|
|
|
ds_put_format(string, "%sduration=%s", colors.param, colors.end);
|
|
|
|
|
ofp_print_duration(string, fs->duration_sec, fs->duration_nsec);
|
|
|
|
|
ds_put_cstr(string, ", ");
|
|
|
|
|
}
|
|
|
|
|
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
if (show_stats || fs->table_id
|
|
|
|
|
|| ofputil_table_map_get_name(table_map, fs->table_id) != NULL) {
|
|
|
|
|
ds_put_format(string, "%stable=%s", colors.special, colors.end);
|
|
|
|
|
ofputil_format_table(fs->table_id, table_map, string);
|
|
|
|
|
ds_put_cstr(string, ", ");
|
2017-06-13 17:09:05 -07:00
|
|
|
|
}
|
|
|
|
|
if (show_stats) {
|
|
|
|
|
ds_put_format(string, "%sn_packets=%s%"PRIu64", ",
|
|
|
|
|
colors.param, colors.end, fs->packet_count);
|
|
|
|
|
ds_put_format(string, "%sn_bytes=%s%"PRIu64", ",
|
|
|
|
|
colors.param, colors.end, fs->byte_count);
|
|
|
|
|
}
|
2012-07-12 13:32:47 -07:00
|
|
|
|
if (fs->idle_timeout != OFP_FLOW_PERMANENT) {
|
2016-03-02 15:56:18 +01:00
|
|
|
|
ds_put_format(string, "%sidle_timeout=%s%"PRIu16", ",
|
|
|
|
|
colors.param, colors.end, fs->idle_timeout);
|
2012-07-12 13:32:47 -07:00
|
|
|
|
}
|
|
|
|
|
if (fs->hard_timeout != OFP_FLOW_PERMANENT) {
|
2016-03-02 15:56:18 +01:00
|
|
|
|
ds_put_format(string, "%shard_timeout=%s%"PRIu16", ",
|
|
|
|
|
colors.param, colors.end, fs->hard_timeout);
|
2012-07-12 13:32:47 -07:00
|
|
|
|
}
|
2012-11-27 17:44:22 +02:00
|
|
|
|
if (fs->flags) {
|
|
|
|
|
ofp_print_flow_flags(string, fs->flags);
|
|
|
|
|
}
|
2014-11-07 18:18:48 +05:30
|
|
|
|
if (fs->importance != 0) {
|
2016-03-02 15:56:18 +01:00
|
|
|
|
ds_put_format(string, "%simportance=%s%"PRIu16", ",
|
|
|
|
|
colors.param, colors.end, fs->importance);
|
2014-11-07 18:18:48 +05:30
|
|
|
|
}
|
2017-06-13 17:09:05 -07:00
|
|
|
|
if (show_stats && fs->idle_age >= 0) {
|
2016-03-02 15:56:18 +01:00
|
|
|
|
ds_put_format(string, "%sidle_age=%s%d, ",
|
|
|
|
|
colors.param, colors.end, fs->idle_age);
|
2012-07-12 13:32:47 -07:00
|
|
|
|
}
|
2017-06-13 17:09:05 -07:00
|
|
|
|
if (show_stats && fs->hard_age >= 0 && fs->hard_age != fs->duration_sec) {
|
2016-03-02 15:56:18 +01:00
|
|
|
|
ds_put_format(string, "%shard_age=%s%d, ",
|
|
|
|
|
colors.param, colors.end, fs->hard_age);
|
2012-07-12 13:32:47 -07:00
|
|
|
|
}
|
|
|
|
|
|
2017-06-13 17:09:05 -07:00
|
|
|
|
/* Print the match, followed by a space (but omit the space if the match
|
|
|
|
|
* was an empty string). */
|
|
|
|
|
size_t length = string->length;
|
2017-05-31 16:06:12 -07:00
|
|
|
|
match_format(&fs->match, port_map, string, fs->priority);
|
2017-06-13 17:09:05 -07:00
|
|
|
|
if (string->length != length) {
|
2012-07-12 13:32:47 -07:00
|
|
|
|
ds_put_char(string, ' ');
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-02 15:56:18 +01:00
|
|
|
|
ds_put_format(string, "%sactions=%s", colors.actions, colors.end);
|
2018-01-12 12:56:12 -08:00
|
|
|
|
struct ofpact_format_params fp = {
|
|
|
|
|
.port_map = port_map,
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
.table_map = table_map,
|
2018-01-12 12:56:12 -08:00
|
|
|
|
.s = string,
|
|
|
|
|
};
|
|
|
|
|
ofpacts_format(fs->ofpacts, fs->ofpacts_len, &fp);
|
2012-07-12 13:32:47 -07:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ofp_print_flow_stats_reply(struct ds *string, const struct ofp_header *oh,
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
const struct ofputil_port_map *port_map,
|
|
|
|
|
const struct ofputil_table_map *table_map)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
2016-02-18 15:13:09 -08:00
|
|
|
|
struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
|
2012-07-03 22:17:14 -07:00
|
|
|
|
struct ofpbuf ofpacts;
|
2018-01-04 22:40:01 -08:00
|
|
|
|
int retval;
|
2009-07-08 13:19:16 -07:00
|
|
|
|
|
2012-07-03 22:17:14 -07:00
|
|
|
|
ofpbuf_init(&ofpacts, 64);
|
2011-03-10 15:02:05 -08:00
|
|
|
|
for (;;) {
|
|
|
|
|
struct ofputil_flow_stats fs;
|
2010-12-08 12:05:20 -08:00
|
|
|
|
|
2012-07-03 22:17:14 -07:00
|
|
|
|
retval = ofputil_decode_flow_stats_reply(&fs, &b, true, &ofpacts);
|
2011-03-10 15:02:05 -08:00
|
|
|
|
if (retval) {
|
2009-07-08 13:19:16 -07:00
|
|
|
|
break;
|
|
|
|
|
}
|
2017-06-13 17:09:05 -07:00
|
|
|
|
ds_put_cstr(string, "\n ");
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
ofp_print_flow_stats(string, &fs, port_map, table_map, true);
|
2012-07-12 13:32:47 -07:00
|
|
|
|
}
|
2012-08-17 13:59:15 -07:00
|
|
|
|
ofpbuf_uninit(&ofpacts);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
|
|
|
|
|
return retval != EOF ? retval : 0;
|
2010-12-07 14:21:38 -08:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2012-07-19 23:23:17 -07:00
|
|
|
|
ofp_print_aggregate_stats_reply(struct ds *string, const struct ofp_header *oh)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
2012-07-19 23:23:17 -07:00
|
|
|
|
struct ofputil_aggregate_stats as;
|
|
|
|
|
enum ofperr error;
|
2009-07-08 13:19:16 -07:00
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
error = ofputil_decode_aggregate_stats_reply(&as, oh);
|
|
|
|
|
if (error) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return error;
|
2012-07-19 23:23:17 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ds_put_format(string, " packet_count=%"PRIu64, as.packet_count);
|
|
|
|
|
ds_put_format(string, " byte_count=%"PRIu64, as.byte_count);
|
|
|
|
|
ds_put_format(string, " flow_count=%"PRIu32, as.flow_count);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
|
|
|
|
|
return 0;
|
2010-12-07 15:07:54 -08:00
|
|
|
|
}
|
|
|
|
|
|
2012-10-06 19:39:49 +09:00
|
|
|
|
static void
|
|
|
|
|
print_port_stat(struct ds *string, const char *leader, uint64_t stat, int more)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
|
|
|
|
ds_put_cstr(string, leader);
|
2011-01-18 11:50:56 -08:00
|
|
|
|
if (stat != UINT64_MAX) {
|
2009-07-08 13:19:16 -07:00
|
|
|
|
ds_put_format(string, "%"PRIu64, stat);
|
|
|
|
|
} else {
|
|
|
|
|
ds_put_char(string, '?');
|
|
|
|
|
}
|
|
|
|
|
if (more) {
|
|
|
|
|
ds_put_cstr(string, ", ");
|
|
|
|
|
} else {
|
|
|
|
|
ds_put_cstr(string, "\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-05-05 09:46:01 +01:00
|
|
|
|
static void
|
|
|
|
|
print_port_stat_cond(struct ds *string, const char *leader, uint64_t stat)
|
|
|
|
|
{
|
|
|
|
|
if (stat != UINT64_MAX) {
|
|
|
|
|
ds_put_format(string, "%s%"PRIu64", ", leader, stat);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ofp_print_ofpst_port_request(struct ds *string, const struct ofp_header *oh,
|
|
|
|
|
const struct ofputil_port_map *port_map)
|
2010-01-19 22:35:18 -08:00
|
|
|
|
{
|
2013-06-19 16:58:44 -07:00
|
|
|
|
ofp_port_t ofp10_port;
|
2012-10-06 19:39:49 +09:00
|
|
|
|
enum ofperr error;
|
|
|
|
|
|
|
|
|
|
error = ofputil_decode_port_stats_request(oh, &ofp10_port);
|
|
|
|
|
if (error) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return error;
|
2012-10-06 19:39:49 +09:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-14 14:43:53 +02:00
|
|
|
|
ds_put_cstr(string, " port_no=");
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ofputil_format_port(ofp10_port, port_map, string);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
|
|
|
|
|
return 0;
|
2010-01-19 22:35:18 -08:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2010-12-06 10:20:20 -08:00
|
|
|
|
ofp_print_ofpst_port_reply(struct ds *string, const struct ofp_header *oh,
|
2017-05-31 16:06:12 -07:00
|
|
|
|
const struct ofputil_port_map *port_map,
|
2010-12-06 10:20:20 -08:00
|
|
|
|
int verbosity)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
2018-01-09 07:55:37 +00:00
|
|
|
|
uint32_t i;
|
2013-11-25 23:38:48 -08:00
|
|
|
|
ds_put_format(string, " %"PRIuSIZE" ports\n", ofputil_count_port_stats(oh));
|
2009-07-08 13:19:16 -07:00
|
|
|
|
if (verbosity < 1) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return 0;
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
2016-02-18 15:13:09 -08:00
|
|
|
|
struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
|
2012-07-19 23:23:17 -07:00
|
|
|
|
for (;;) {
|
2012-10-06 19:39:49 +09:00
|
|
|
|
struct ofputil_port_stats ps;
|
|
|
|
|
int retval;
|
|
|
|
|
|
|
|
|
|
retval = ofputil_decode_port_stats(&ps, &b);
|
|
|
|
|
if (retval) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return retval != EOF ? retval : 0;
|
2012-07-19 23:23:17 -07:00
|
|
|
|
}
|
|
|
|
|
|
2013-01-14 14:43:53 +02:00
|
|
|
|
ds_put_cstr(string, " port ");
|
2013-06-19 16:58:44 -07:00
|
|
|
|
if (ofp_to_u16(ps.port_no) < 10) {
|
2013-01-14 14:43:53 +02:00
|
|
|
|
ds_put_char(string, ' ');
|
|
|
|
|
}
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ofputil_format_port(ps.port_no, port_map, string);
|
2009-07-08 13:19:16 -07:00
|
|
|
|
|
2012-10-06 19:39:49 +09:00
|
|
|
|
ds_put_cstr(string, ": rx ");
|
|
|
|
|
print_port_stat(string, "pkts=", ps.stats.rx_packets, 1);
|
|
|
|
|
print_port_stat(string, "bytes=", ps.stats.rx_bytes, 1);
|
|
|
|
|
print_port_stat(string, "drop=", ps.stats.rx_dropped, 1);
|
|
|
|
|
print_port_stat(string, "errs=", ps.stats.rx_errors, 1);
|
|
|
|
|
print_port_stat(string, "frame=", ps.stats.rx_frame_errors, 1);
|
|
|
|
|
print_port_stat(string, "over=", ps.stats.rx_over_errors, 1);
|
|
|
|
|
print_port_stat(string, "crc=", ps.stats.rx_crc_errors, 0);
|
2009-07-08 13:19:16 -07:00
|
|
|
|
|
|
|
|
|
ds_put_cstr(string, " tx ");
|
2012-10-06 19:39:49 +09:00
|
|
|
|
print_port_stat(string, "pkts=", ps.stats.tx_packets, 1);
|
|
|
|
|
print_port_stat(string, "bytes=", ps.stats.tx_bytes, 1);
|
|
|
|
|
print_port_stat(string, "drop=", ps.stats.tx_dropped, 1);
|
|
|
|
|
print_port_stat(string, "errs=", ps.stats.tx_errors, 1);
|
|
|
|
|
print_port_stat(string, "coll=", ps.stats.collisions, 0);
|
2013-05-30 12:49:59 -07:00
|
|
|
|
|
|
|
|
|
if (ps.duration_sec != UINT32_MAX) {
|
|
|
|
|
ds_put_cstr(string, " duration=");
|
|
|
|
|
ofp_print_duration(string, ps.duration_sec, ps.duration_nsec);
|
|
|
|
|
ds_put_char(string, '\n');
|
|
|
|
|
}
|
2016-05-05 09:46:01 +01:00
|
|
|
|
struct ds string_ext_stats = DS_EMPTY_INITIALIZER;
|
|
|
|
|
|
|
|
|
|
ds_init(&string_ext_stats);
|
|
|
|
|
|
|
|
|
|
print_port_stat_cond(&string_ext_stats, "1_to_64_packets=",
|
|
|
|
|
ps.stats.rx_1_to_64_packets);
|
|
|
|
|
print_port_stat_cond(&string_ext_stats, "65_to_127_packets=",
|
|
|
|
|
ps.stats.rx_65_to_127_packets);
|
|
|
|
|
print_port_stat_cond(&string_ext_stats, "128_to_255_packets=",
|
|
|
|
|
ps.stats.rx_128_to_255_packets);
|
|
|
|
|
print_port_stat_cond(&string_ext_stats, "256_to_511_packets=",
|
|
|
|
|
ps.stats.rx_256_to_511_packets);
|
|
|
|
|
print_port_stat_cond(&string_ext_stats, "512_to_1023_packets=",
|
|
|
|
|
ps.stats.rx_512_to_1023_packets);
|
|
|
|
|
print_port_stat_cond(&string_ext_stats, "1024_to_1522_packets=",
|
|
|
|
|
ps.stats.rx_1024_to_1522_packets);
|
|
|
|
|
print_port_stat_cond(&string_ext_stats, "1523_to_max_packets=",
|
|
|
|
|
ps.stats.rx_1523_to_max_packets);
|
|
|
|
|
print_port_stat_cond(&string_ext_stats, "broadcast_packets=",
|
|
|
|
|
ps.stats.rx_broadcast_packets);
|
|
|
|
|
print_port_stat_cond(&string_ext_stats, "undersized_errors=",
|
|
|
|
|
ps.stats.rx_undersized_errors);
|
|
|
|
|
print_port_stat_cond(&string_ext_stats, "oversize_errors=",
|
|
|
|
|
ps.stats.rx_oversize_errors);
|
|
|
|
|
print_port_stat_cond(&string_ext_stats, "rx_fragmented_errors=",
|
|
|
|
|
ps.stats.rx_fragmented_errors);
|
|
|
|
|
print_port_stat_cond(&string_ext_stats, "rx_jabber_errors=",
|
|
|
|
|
ps.stats.rx_jabber_errors);
|
|
|
|
|
|
|
|
|
|
if (string_ext_stats.length != 0) {
|
|
|
|
|
/* If at least one statistics counter is reported: */
|
|
|
|
|
ds_put_cstr(string, " rx rfc2819 ");
|
|
|
|
|
ds_put_buffer(string, string_ext_stats.string,
|
|
|
|
|
string_ext_stats.length);
|
|
|
|
|
ds_put_cstr(string, "\n");
|
|
|
|
|
ds_destroy(&string_ext_stats);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ds_init(&string_ext_stats);
|
|
|
|
|
|
|
|
|
|
print_port_stat_cond(&string_ext_stats, "1_to_64_packets=",
|
|
|
|
|
ps.stats.tx_1_to_64_packets);
|
|
|
|
|
print_port_stat_cond(&string_ext_stats, "65_to_127_packets=",
|
|
|
|
|
ps.stats.tx_65_to_127_packets);
|
|
|
|
|
print_port_stat_cond(&string_ext_stats, "128_to_255_packets=",
|
|
|
|
|
ps.stats.tx_128_to_255_packets);
|
|
|
|
|
print_port_stat_cond(&string_ext_stats, "256_to_511_packets=",
|
|
|
|
|
ps.stats.tx_256_to_511_packets);
|
|
|
|
|
print_port_stat_cond(&string_ext_stats, "512_to_1023_packets=",
|
|
|
|
|
ps.stats.tx_512_to_1023_packets);
|
|
|
|
|
print_port_stat_cond(&string_ext_stats, "1024_to_1522_packets=",
|
|
|
|
|
ps.stats.tx_1024_to_1522_packets);
|
|
|
|
|
print_port_stat_cond(&string_ext_stats, "1523_to_max_packets=",
|
|
|
|
|
ps.stats.tx_1523_to_max_packets);
|
|
|
|
|
print_port_stat_cond(&string_ext_stats, "multicast_packets=",
|
|
|
|
|
ps.stats.tx_multicast_packets);
|
|
|
|
|
print_port_stat_cond(&string_ext_stats, "broadcast_packets=",
|
|
|
|
|
ps.stats.tx_broadcast_packets);
|
|
|
|
|
|
|
|
|
|
if (string_ext_stats.length != 0) {
|
|
|
|
|
/* If at least one statistics counter is reported: */
|
|
|
|
|
ds_put_cstr(string, " tx rfc2819 ");
|
|
|
|
|
ds_put_buffer(string, string_ext_stats.string,
|
|
|
|
|
string_ext_stats.length);
|
|
|
|
|
ds_put_cstr(string, "\n");
|
|
|
|
|
ds_destroy(&string_ext_stats);
|
|
|
|
|
}
|
2018-01-09 07:55:37 +00:00
|
|
|
|
|
|
|
|
|
if (ps.custom_stats.size) {
|
|
|
|
|
ds_put_cstr(string, " CUSTOM Statistics");
|
|
|
|
|
for (i = 0; i < ps.custom_stats.size; i++) {
|
|
|
|
|
/* 3 counters in the row */
|
|
|
|
|
if (ps.custom_stats.counters[i].name[0]) {
|
|
|
|
|
if (i % 3 == 0) {
|
|
|
|
|
ds_put_cstr(string, "\n");
|
|
|
|
|
ds_put_cstr(string, " ");
|
|
|
|
|
} else {
|
|
|
|
|
ds_put_char(string, ' ');
|
|
|
|
|
}
|
|
|
|
|
ds_put_format(string, "%s=%"PRIu64",",
|
|
|
|
|
ps.custom_stats.counters[i].name,
|
|
|
|
|
ps.custom_stats.counters[i].value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ds_put_cstr(string, "\n");
|
|
|
|
|
}
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
ofp_print_table_stats_reply(struct ds *string, const struct ofp_header *oh,
|
|
|
|
|
const struct ofputil_table_map *table_map)
|
2012-08-09 17:49:34 +09:00
|
|
|
|
{
|
2016-02-18 15:13:09 -08:00
|
|
|
|
struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
|
2012-08-09 17:49:34 +09:00
|
|
|
|
ofpraw_pull_assert(&b);
|
|
|
|
|
|
2015-07-06 22:15:40 -07:00
|
|
|
|
struct ofputil_table_features prev_features;
|
|
|
|
|
struct ofputil_table_stats prev_stats;
|
|
|
|
|
for (int i = 0;; i++) {
|
2014-08-11 11:31:45 -07:00
|
|
|
|
struct ofputil_table_features features;
|
|
|
|
|
struct ofputil_table_stats stats;
|
|
|
|
|
int retval;
|
2012-07-19 23:23:17 -07:00
|
|
|
|
|
2014-08-11 11:31:45 -07:00
|
|
|
|
retval = ofputil_decode_table_stats_reply(&b, &stats, &features);
|
|
|
|
|
if (retval) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return retval != EOF ? retval : 0;
|
2012-07-19 23:23:17 -07:00
|
|
|
|
}
|
|
|
|
|
|
2015-07-06 22:15:40 -07:00
|
|
|
|
ds_put_char(string, '\n');
|
|
|
|
|
ofp_print_table_features(string,
|
|
|
|
|
&features, i ? &prev_features : NULL,
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
&stats, i ? &prev_stats : NULL,
|
|
|
|
|
table_map);
|
2015-07-06 22:15:40 -07:00
|
|
|
|
prev_features = features;
|
|
|
|
|
prev_stats = stats;
|
2012-08-09 17:49:34 +09:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-09-16 15:36:57 -07:00
|
|
|
|
static void
|
|
|
|
|
ofp_print_queue_name(struct ds *string, uint32_t queue_id)
|
|
|
|
|
{
|
|
|
|
|
if (queue_id == OFPQ_ALL) {
|
|
|
|
|
ds_put_cstr(string, "ALL");
|
|
|
|
|
} else {
|
|
|
|
|
ds_put_format(string, "%"PRIu32, queue_id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ofp_print_ofpst_queue_request(struct ds *string, const struct ofp_header *oh,
|
|
|
|
|
const struct ofputil_port_map *port_map)
|
2010-09-16 15:36:57 -07:00
|
|
|
|
{
|
2012-10-12 13:03:04 +09:00
|
|
|
|
struct ofputil_queue_stats_request oqsr;
|
|
|
|
|
enum ofperr error;
|
|
|
|
|
|
|
|
|
|
error = ofputil_decode_queue_stats_request(oh, &oqsr);
|
|
|
|
|
if (error) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return error;
|
2012-10-12 13:03:04 +09:00
|
|
|
|
}
|
2012-07-19 23:23:17 -07:00
|
|
|
|
|
2015-12-24 15:29:26 -08:00
|
|
|
|
ds_put_cstr(string, " port=");
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ofputil_format_port(oqsr.port_no, port_map, string);
|
2010-09-16 15:36:57 -07:00
|
|
|
|
|
|
|
|
|
ds_put_cstr(string, " queue=");
|
2012-10-12 13:03:04 +09:00
|
|
|
|
ofp_print_queue_name(string, oqsr.queue_id);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
|
|
|
|
|
return 0;
|
2012-10-06 19:39:49 +09:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2010-12-06 10:20:20 -08:00
|
|
|
|
ofp_print_ofpst_queue_reply(struct ds *string, const struct ofp_header *oh,
|
2017-05-31 16:06:12 -07:00
|
|
|
|
const struct ofputil_port_map *port_map,
|
2010-12-06 10:20:20 -08:00
|
|
|
|
int verbosity)
|
2010-09-16 15:36:57 -07:00
|
|
|
|
{
|
2013-11-25 23:38:48 -08:00
|
|
|
|
ds_put_format(string, " %"PRIuSIZE" queues\n", ofputil_count_queue_stats(oh));
|
2010-09-16 15:36:57 -07:00
|
|
|
|
if (verbosity < 1) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return 0;
|
2010-09-16 15:36:57 -07:00
|
|
|
|
}
|
|
|
|
|
|
2016-02-18 15:13:09 -08:00
|
|
|
|
struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
|
2012-07-19 23:23:17 -07:00
|
|
|
|
for (;;) {
|
2012-10-12 13:03:04 +09:00
|
|
|
|
struct ofputil_queue_stats qs;
|
|
|
|
|
int retval;
|
|
|
|
|
|
|
|
|
|
retval = ofputil_decode_queue_stats(&qs, &b);
|
|
|
|
|
if (retval) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return retval != EOF ? retval : 0;
|
2012-07-19 23:23:17 -07:00
|
|
|
|
}
|
|
|
|
|
|
2010-09-16 15:36:57 -07:00
|
|
|
|
ds_put_cstr(string, " port ");
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ofputil_format_port(qs.port_no, port_map, string);
|
2010-09-16 15:36:57 -07:00
|
|
|
|
ds_put_cstr(string, " queue ");
|
2012-10-12 13:03:04 +09:00
|
|
|
|
ofp_print_queue_name(string, qs.queue_id);
|
2010-09-16 15:36:57 -07:00
|
|
|
|
ds_put_cstr(string, ": ");
|
|
|
|
|
|
2013-07-17 15:56:22 -07:00
|
|
|
|
print_port_stat(string, "bytes=", qs.tx_bytes, 1);
|
|
|
|
|
print_port_stat(string, "pkts=", qs.tx_packets, 1);
|
|
|
|
|
print_port_stat(string, "errors=", qs.tx_errors, 1);
|
|
|
|
|
|
|
|
|
|
ds_put_cstr(string, "duration=");
|
|
|
|
|
if (qs.duration_sec != UINT32_MAX) {
|
|
|
|
|
ofp_print_duration(string, qs.duration_sec, qs.duration_nsec);
|
|
|
|
|
} else {
|
|
|
|
|
ds_put_char(string, '?');
|
|
|
|
|
}
|
|
|
|
|
ds_put_char(string, '\n');
|
2010-09-16 15:36:57 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2014-05-07 23:18:46 -07:00
|
|
|
|
ofp_print_ofpst_port_desc_request(struct ds *string,
|
2017-05-31 16:06:12 -07:00
|
|
|
|
const struct ofp_header *oh,
|
|
|
|
|
const struct ofputil_port_map *port_map)
|
2014-05-07 23:18:46 -07:00
|
|
|
|
{
|
|
|
|
|
enum ofperr error;
|
|
|
|
|
ofp_port_t port;
|
|
|
|
|
|
|
|
|
|
error = ofputil_decode_port_desc_stats_request(oh, &port);
|
|
|
|
|
if (error) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return error;
|
2014-05-07 23:18:46 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ds_put_cstr(string, " port=");
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ofputil_format_port(port, port_map, string);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
|
|
|
|
|
return 0;
|
2014-05-07 23:18:46 -07:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2012-05-04 14:42:04 -07:00
|
|
|
|
ofp_print_ofpst_port_desc_reply(struct ds *string,
|
|
|
|
|
const struct ofp_header *oh)
|
|
|
|
|
{
|
2016-02-18 15:13:09 -08:00
|
|
|
|
struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
|
2012-07-19 23:23:17 -07:00
|
|
|
|
ofpraw_pull_assert(&b);
|
2012-05-04 14:42:04 -07:00
|
|
|
|
ds_put_char(string, '\n');
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_phy_ports(string, oh->version, &b);
|
2012-05-04 14:42:04 -07:00
|
|
|
|
}
|
|
|
|
|
|
2009-07-08 13:19:16 -07:00
|
|
|
|
static void
|
2014-05-27 18:05:37 +09:00
|
|
|
|
ofp_print_stats(struct ds *string, const struct ofp_header *oh)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
2012-07-19 23:23:17 -07:00
|
|
|
|
uint16_t flags = ofpmp_flags(oh);
|
2010-12-06 10:20:20 -08:00
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
if (flags) {
|
2010-12-06 10:20:20 -08:00
|
|
|
|
ds_put_cstr(string, " flags=");
|
2014-05-27 18:05:37 +09:00
|
|
|
|
if ((!ofpmsg_is_stat_request(oh) || oh->version >= OFP13_VERSION)
|
|
|
|
|
&& (flags & OFPSF_REPLY_MORE)) {
|
2009-07-08 13:19:16 -07:00
|
|
|
|
ds_put_cstr(string, "[more]");
|
|
|
|
|
flags &= ~OFPSF_REPLY_MORE;
|
|
|
|
|
}
|
|
|
|
|
if (flags) {
|
2010-12-06 10:20:20 -08:00
|
|
|
|
ds_put_format(string, "[***unknown flags 0x%04"PRIx16"***]",
|
|
|
|
|
flags);
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2010-12-06 10:20:20 -08:00
|
|
|
|
ofp_print_echo(struct ds *string, const struct ofp_header *oh, int verbosity)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
2010-12-06 10:20:20 -08:00
|
|
|
|
size_t len = ntohs(oh->length);
|
2009-07-08 13:19:16 -07:00
|
|
|
|
|
2013-11-25 23:38:48 -08:00
|
|
|
|
ds_put_format(string, " %"PRIuSIZE" bytes of payload\n", len - sizeof *oh);
|
2009-07-08 13:19:16 -07:00
|
|
|
|
if (verbosity > 1) {
|
2010-12-06 10:20:20 -08:00
|
|
|
|
ds_put_hex_dump(string, oh + 1, len - sizeof *oh, 0, true);
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
2018-01-04 22:40:01 -08:00
|
|
|
|
|
|
|
|
|
return 0;
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
2010-12-07 14:36:18 -08:00
|
|
|
|
static void
|
2013-10-22 11:40:03 +03:00
|
|
|
|
ofp_print_role_generic(struct ds *string, enum ofp12_controller_role role,
|
|
|
|
|
uint64_t generation_id)
|
2010-12-07 14:36:18 -08:00
|
|
|
|
{
|
|
|
|
|
ds_put_cstr(string, " role=");
|
2012-12-28 18:28:49 +02:00
|
|
|
|
|
2013-10-22 11:40:03 +03:00
|
|
|
|
switch (role) {
|
2013-02-11 23:55:31 -08:00
|
|
|
|
case OFPCR12_ROLE_NOCHANGE:
|
|
|
|
|
ds_put_cstr(string, "nochange");
|
|
|
|
|
break;
|
|
|
|
|
case OFPCR12_ROLE_EQUAL:
|
2012-12-28 18:28:49 +02:00
|
|
|
|
ds_put_cstr(string, "equal"); /* OF 1.2 wording */
|
|
|
|
|
break;
|
2013-02-11 23:55:31 -08:00
|
|
|
|
case OFPCR12_ROLE_MASTER:
|
2010-12-07 14:36:18 -08:00
|
|
|
|
ds_put_cstr(string, "master");
|
2012-12-28 18:28:49 +02:00
|
|
|
|
break;
|
2013-02-11 23:55:31 -08:00
|
|
|
|
case OFPCR12_ROLE_SLAVE:
|
2010-12-07 14:36:18 -08:00
|
|
|
|
ds_put_cstr(string, "slave");
|
2012-12-28 18:28:49 +02:00
|
|
|
|
break;
|
|
|
|
|
default:
|
2013-12-17 10:32:12 -08:00
|
|
|
|
OVS_NOT_REACHED();
|
2012-12-28 18:28:49 +02:00
|
|
|
|
}
|
|
|
|
|
|
2013-10-22 11:40:03 +03:00
|
|
|
|
if (generation_id != UINT64_MAX) {
|
|
|
|
|
ds_put_format(string, " generation_id=%"PRIu64, generation_id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2013-10-22 11:40:03 +03:00
|
|
|
|
ofp_print_role_message(struct ds *string, const struct ofp_header *oh)
|
|
|
|
|
{
|
|
|
|
|
struct ofputil_role_request rr;
|
|
|
|
|
enum ofperr error;
|
|
|
|
|
|
|
|
|
|
error = ofputil_decode_role_message(oh, &rr);
|
|
|
|
|
if (error) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return error;
|
2013-10-22 11:40:03 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ofp_print_role_generic(string, rr.role, rr.have_generation_id ? rr.generation_id : UINT64_MAX);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
|
|
|
|
|
return 0;
|
2013-10-22 11:40:03 +03:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2013-10-22 11:40:03 +03:00
|
|
|
|
ofp_print_role_status_message(struct ds *string, const struct ofp_header *oh)
|
|
|
|
|
{
|
|
|
|
|
struct ofputil_role_status rs;
|
|
|
|
|
enum ofperr error;
|
|
|
|
|
|
|
|
|
|
error = ofputil_decode_role_status(oh, &rs);
|
|
|
|
|
if (error) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return error;
|
2013-10-22 11:40:03 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ofp_print_role_generic(string, rs.role, rs.generation_id);
|
|
|
|
|
|
|
|
|
|
ds_put_cstr(string, " reason=");
|
|
|
|
|
|
|
|
|
|
switch (rs.reason) {
|
|
|
|
|
case OFPCRR_MASTER_REQUEST:
|
|
|
|
|
ds_put_cstr(string, "master_request");
|
|
|
|
|
break;
|
|
|
|
|
case OFPCRR_CONFIG:
|
|
|
|
|
ds_put_cstr(string, "configuration_changed");
|
|
|
|
|
break;
|
|
|
|
|
case OFPCRR_EXPERIMENTER:
|
|
|
|
|
ds_put_cstr(string, "experimenter_data_changed");
|
|
|
|
|
break;
|
2015-11-30 16:52:47 +05:30
|
|
|
|
case OFPCRR_N_REASONS:
|
2013-10-22 11:40:03 +03:00
|
|
|
|
default:
|
2017-05-26 13:22:26 -07:00
|
|
|
|
ds_put_cstr(string, "(unknown)");
|
|
|
|
|
break;
|
2010-12-07 14:36:18 -08:00
|
|
|
|
}
|
2018-01-04 22:40:01 -08:00
|
|
|
|
|
|
|
|
|
return 0;
|
2010-12-07 14:36:18 -08:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2018-02-15 14:38:28 -08:00
|
|
|
|
ofp_print_nxt_flow_mod_table_id(struct ds *string, const struct ofp_header *oh)
|
2011-05-12 09:58:01 -07:00
|
|
|
|
{
|
2018-02-15 14:38:28 -08:00
|
|
|
|
bool enable = ofputil_decode_nx_flow_mod_table_id(oh);
|
|
|
|
|
ds_put_format(string, " %s", enable ? "enable" : "disable");
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return 0;
|
2011-05-12 09:58:01 -07:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2018-02-15 14:38:28 -08:00
|
|
|
|
ofp_print_nxt_set_flow_format(struct ds *string, const struct ofp_header *oh)
|
2010-12-07 13:22:46 -08:00
|
|
|
|
{
|
2018-02-15 14:38:28 -08:00
|
|
|
|
enum ofputil_protocol p = ofputil_decode_nx_set_flow_format(oh);
|
|
|
|
|
ds_put_format(string, " format=%s",
|
|
|
|
|
p == OFPUTIL_P_OF10_STD ? "openflow10"
|
|
|
|
|
: p == OFPUTIL_P_OF10_NXM ? "nxm"
|
|
|
|
|
: "(unknown)");
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return 0;
|
2010-12-07 13:22:46 -08:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2011-12-09 15:48:26 -08:00
|
|
|
|
ofp_print_nxt_set_packet_in_format(struct ds *string,
|
2012-01-12 11:35:50 -08:00
|
|
|
|
const struct nx_set_packet_in_format *nspf)
|
2011-12-09 15:48:26 -08:00
|
|
|
|
{
|
|
|
|
|
uint32_t format = ntohl(nspf->format);
|
|
|
|
|
|
|
|
|
|
ds_put_cstr(string, " format=");
|
|
|
|
|
if (ofputil_packet_in_format_is_valid(format)) {
|
|
|
|
|
ds_put_cstr(string, ofputil_packet_in_format_to_string(format));
|
|
|
|
|
} else {
|
|
|
|
|
ds_put_format(string, "%"PRIu32, format);
|
|
|
|
|
}
|
2018-01-04 22:40:01 -08:00
|
|
|
|
|
|
|
|
|
return 0;
|
2011-12-09 15:48:26 -08:00
|
|
|
|
}
|
|
|
|
|
|
2013-06-12 14:49:19 -07:00
|
|
|
|
/* Returns a string form of 'reason'. The return value is either a statically
|
|
|
|
|
* allocated constant string or the 'bufsize'-byte buffer 'reasonbuf'.
|
|
|
|
|
* 'bufsize' should be at least OFP_PORT_REASON_BUFSIZE. */
|
|
|
|
|
#define OFP_PORT_REASON_BUFSIZE (INT_STRLEN(int) + 1)
|
2012-02-09 14:06:35 -08:00
|
|
|
|
static const char *
|
2013-06-12 14:49:19 -07:00
|
|
|
|
ofp_port_reason_to_string(enum ofp_port_reason reason,
|
|
|
|
|
char *reasonbuf, size_t bufsize)
|
2012-02-09 14:06:35 -08:00
|
|
|
|
{
|
|
|
|
|
switch (reason) {
|
|
|
|
|
case OFPPR_ADD:
|
|
|
|
|
return "add";
|
|
|
|
|
|
|
|
|
|
case OFPPR_DELETE:
|
|
|
|
|
return "delete";
|
|
|
|
|
|
|
|
|
|
case OFPPR_MODIFY:
|
|
|
|
|
return "modify";
|
|
|
|
|
|
2015-11-30 16:52:47 +05:30
|
|
|
|
case OFPPR_N_REASONS:
|
2012-02-09 14:06:35 -08:00
|
|
|
|
default:
|
2013-06-12 14:49:19 -07:00
|
|
|
|
snprintf(reasonbuf, bufsize, "%d", (int) reason);
|
|
|
|
|
return reasonbuf;
|
2012-02-09 14:06:35 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
ofproto: Implement OF1.4 Set/Get asynchronous configuration messages.
This patch adds support for Openflow1.4 set/get asynchronous configuration
messages. OpenVSwitch already supports set/get asynchronous configuration
messages for Openflow1.3. In this patch OFPT_SET_ASYNC_CONFIG message
allows the controllers to set the configuration for OFPT_ROLE_STATUS,
OFPT_TABLE_STATUS and OFPT_REQUESTFORWARD in addition to the Openflow1.3
messages. In a OFPT_SET_ASYNC, only the properties that shall be changed
need to be included, properties that are omitted from the message are
unchanged.
The OFPT_GET_ASYNC_CONFIG is used to query the asynchronous configuration
of switch. In a OFPT_GET_ASYNC_REPLY message, all properties must be
included.
According to Openflow1.4 the initial configuration shall be:
- In the “master” or “equal” role, enable all OFPT_PACKET_IN messages,
except those with reason OFPR_INVALID_TTL, enable all OFPT_PORT_STATUS
and OFPT_FLOW_REMOVED messages, and disable all OFPT_ROLE_STATUS,
OFPT_TABLE_STATUS and OFPT_REQUESTFORWARD messages.
- In the “slave” role, enable all OFPT_PORT_STATUS messages and disable
all OFPT_PACKET_IN, OFPT_FLOW_REMOVED, OFPT_ROLE_STATUS,
OFPT_TABLE_STATUS and OFPT_REQUESTFORWARD messages.
Signed-off-by: Niti Rohilla <niti.rohilla@tcs.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
2015-07-23 17:05:44 +05:30
|
|
|
|
/* Returns a string form of 'reason'. The return value is either a statically
|
|
|
|
|
* allocated constant string or the 'bufsize'-byte buffer 'reasonbuf'.
|
|
|
|
|
* 'bufsize' should be at least OFP_ASYNC_CONFIG_REASON_BUFSIZE. */
|
|
|
|
|
static const char*
|
|
|
|
|
ofp_role_reason_to_string(enum ofp14_controller_role_reason reason,
|
|
|
|
|
char *reasonbuf, size_t bufsize)
|
|
|
|
|
{
|
|
|
|
|
switch (reason) {
|
|
|
|
|
case OFPCRR_MASTER_REQUEST:
|
|
|
|
|
return "master_request";
|
|
|
|
|
|
|
|
|
|
case OFPCRR_CONFIG:
|
|
|
|
|
return "configuration_changed";
|
|
|
|
|
|
|
|
|
|
case OFPCRR_EXPERIMENTER:
|
|
|
|
|
return "experimenter_data_changed";
|
|
|
|
|
|
2015-11-30 16:52:47 +05:30
|
|
|
|
case OFPCRR_N_REASONS:
|
ofproto: Implement OF1.4 Set/Get asynchronous configuration messages.
This patch adds support for Openflow1.4 set/get asynchronous configuration
messages. OpenVSwitch already supports set/get asynchronous configuration
messages for Openflow1.3. In this patch OFPT_SET_ASYNC_CONFIG message
allows the controllers to set the configuration for OFPT_ROLE_STATUS,
OFPT_TABLE_STATUS and OFPT_REQUESTFORWARD in addition to the Openflow1.3
messages. In a OFPT_SET_ASYNC, only the properties that shall be changed
need to be included, properties that are omitted from the message are
unchanged.
The OFPT_GET_ASYNC_CONFIG is used to query the asynchronous configuration
of switch. In a OFPT_GET_ASYNC_REPLY message, all properties must be
included.
According to Openflow1.4 the initial configuration shall be:
- In the “master” or “equal” role, enable all OFPT_PACKET_IN messages,
except those with reason OFPR_INVALID_TTL, enable all OFPT_PORT_STATUS
and OFPT_FLOW_REMOVED messages, and disable all OFPT_ROLE_STATUS,
OFPT_TABLE_STATUS and OFPT_REQUESTFORWARD messages.
- In the “slave” role, enable all OFPT_PORT_STATUS messages and disable
all OFPT_PACKET_IN, OFPT_FLOW_REMOVED, OFPT_ROLE_STATUS,
OFPT_TABLE_STATUS and OFPT_REQUESTFORWARD messages.
Signed-off-by: Niti Rohilla <niti.rohilla@tcs.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
2015-07-23 17:05:44 +05:30
|
|
|
|
default:
|
|
|
|
|
snprintf(reasonbuf, bufsize, "%d", (int) reason);
|
|
|
|
|
return reasonbuf;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Returns a string form of 'reason'. The return value is either a statically
|
|
|
|
|
* allocated constant string or the 'bufsize'-byte buffer 'reasonbuf'.
|
|
|
|
|
* 'bufsize' should be at least OFP_ASYNC_CONFIG_REASON_BUFSIZE. */
|
|
|
|
|
static const char*
|
|
|
|
|
ofp_table_reason_to_string(enum ofp14_table_reason reason,
|
|
|
|
|
char *reasonbuf, size_t bufsize)
|
|
|
|
|
{
|
|
|
|
|
switch (reason) {
|
|
|
|
|
case OFPTR_VACANCY_DOWN:
|
|
|
|
|
return "vacancy_down";
|
|
|
|
|
|
|
|
|
|
case OFPTR_VACANCY_UP:
|
|
|
|
|
return "vacancy_up";
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
snprintf(reasonbuf, bufsize, "%d", (int) reason);
|
|
|
|
|
return reasonbuf;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Returns a string form of 'reason'. The return value is either a statically
|
|
|
|
|
* allocated constant string or the 'bufsize'-byte buffer 'reasonbuf'.
|
|
|
|
|
* 'bufsize' should be at least OFP_ASYNC_CONFIG_REASON_BUFSIZE. */
|
|
|
|
|
static const char*
|
|
|
|
|
ofp_requestforward_reason_to_string(enum ofp14_requestforward_reason reason,
|
|
|
|
|
char *reasonbuf, size_t bufsize)
|
|
|
|
|
{
|
|
|
|
|
switch (reason) {
|
|
|
|
|
case OFPRFR_GROUP_MOD:
|
|
|
|
|
return "group_mod_request";
|
|
|
|
|
|
|
|
|
|
case OFPRFR_METER_MOD:
|
|
|
|
|
return "meter_mod_request";
|
|
|
|
|
|
2015-11-30 16:52:47 +05:30
|
|
|
|
case OFPRFR_N_REASONS:
|
ofproto: Implement OF1.4 Set/Get asynchronous configuration messages.
This patch adds support for Openflow1.4 set/get asynchronous configuration
messages. OpenVSwitch already supports set/get asynchronous configuration
messages for Openflow1.3. In this patch OFPT_SET_ASYNC_CONFIG message
allows the controllers to set the configuration for OFPT_ROLE_STATUS,
OFPT_TABLE_STATUS and OFPT_REQUESTFORWARD in addition to the Openflow1.3
messages. In a OFPT_SET_ASYNC, only the properties that shall be changed
need to be included, properties that are omitted from the message are
unchanged.
The OFPT_GET_ASYNC_CONFIG is used to query the asynchronous configuration
of switch. In a OFPT_GET_ASYNC_REPLY message, all properties must be
included.
According to Openflow1.4 the initial configuration shall be:
- In the “master” or “equal” role, enable all OFPT_PACKET_IN messages,
except those with reason OFPR_INVALID_TTL, enable all OFPT_PORT_STATUS
and OFPT_FLOW_REMOVED messages, and disable all OFPT_ROLE_STATUS,
OFPT_TABLE_STATUS and OFPT_REQUESTFORWARD messages.
- In the “slave” role, enable all OFPT_PORT_STATUS messages and disable
all OFPT_PACKET_IN, OFPT_FLOW_REMOVED, OFPT_ROLE_STATUS,
OFPT_TABLE_STATUS and OFPT_REQUESTFORWARD messages.
Signed-off-by: Niti Rohilla <niti.rohilla@tcs.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
2015-07-23 17:05:44 +05:30
|
|
|
|
default:
|
|
|
|
|
snprintf(reasonbuf, bufsize, "%d", (int) reason);
|
|
|
|
|
return reasonbuf;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
|
ofp_async_config_reason_to_string(uint32_t reason,
|
|
|
|
|
enum ofputil_async_msg_type type,
|
|
|
|
|
char *reasonbuf, size_t bufsize)
|
|
|
|
|
{
|
|
|
|
|
switch (type) {
|
|
|
|
|
case OAM_PACKET_IN:
|
|
|
|
|
return ofputil_packet_in_reason_to_string(reason, reasonbuf, bufsize);
|
|
|
|
|
|
|
|
|
|
case OAM_PORT_STATUS:
|
|
|
|
|
return ofp_port_reason_to_string(reason, reasonbuf, bufsize);
|
|
|
|
|
|
|
|
|
|
case OAM_FLOW_REMOVED:
|
|
|
|
|
return ofp_flow_removed_reason_to_string(reason, reasonbuf, bufsize);
|
|
|
|
|
|
|
|
|
|
case OAM_ROLE_STATUS:
|
|
|
|
|
return ofp_role_reason_to_string(reason, reasonbuf, bufsize);
|
|
|
|
|
|
|
|
|
|
case OAM_TABLE_STATUS:
|
|
|
|
|
return ofp_table_reason_to_string(reason, reasonbuf, bufsize);
|
|
|
|
|
|
|
|
|
|
case OAM_REQUESTFORWARD:
|
|
|
|
|
return ofp_requestforward_reason_to_string(reason, reasonbuf, bufsize);
|
|
|
|
|
|
|
|
|
|
case OAM_N_TYPES:
|
|
|
|
|
default:
|
|
|
|
|
return "Unknown asynchronous configuration message type";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define OFP_ASYNC_CONFIG_REASON_BUFSIZE (INT_STRLEN(int) + 1)
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2016-01-14 22:16:34 -08:00
|
|
|
|
ofp_print_set_async_config(struct ds *string, const struct ofp_header *oh,
|
2017-08-02 15:03:06 -07:00
|
|
|
|
enum ofptype ofptype)
|
2012-02-09 14:06:35 -08:00
|
|
|
|
{
|
2016-01-14 22:16:34 -08:00
|
|
|
|
struct ofputil_async_cfg basis = OFPUTIL_ASYNC_CFG_INIT;
|
|
|
|
|
struct ofputil_async_cfg ac;
|
2012-02-09 14:06:35 -08:00
|
|
|
|
|
2017-08-02 15:03:06 -07:00
|
|
|
|
bool is_reply = ofptype == OFPTYPE_GET_ASYNC_REPLY;
|
2016-01-14 22:16:34 -08:00
|
|
|
|
enum ofperr error = ofputil_decode_set_async_config(oh, is_reply,
|
|
|
|
|
&basis, &ac);
|
|
|
|
|
if (error) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return error;
|
2016-01-14 22:16:34 -08:00
|
|
|
|
}
|
2013-06-12 14:49:19 -07:00
|
|
|
|
|
2016-01-14 22:16:34 -08:00
|
|
|
|
for (int i = 0; i < 2; i++) {
|
|
|
|
|
ds_put_format(string, "\n %s:\n", i == 0 ? "master" : "slave");
|
|
|
|
|
for (uint32_t type = 0; type < OAM_N_TYPES; type++) {
|
|
|
|
|
ds_put_format(string, "%16s:",
|
|
|
|
|
ofputil_async_msg_type_to_string(type));
|
2012-02-09 14:06:35 -08:00
|
|
|
|
|
2016-01-14 22:16:34 -08:00
|
|
|
|
uint32_t role = i == 0 ? ac.master[type] : ac.slave[type];
|
|
|
|
|
for (int j = 0; j < 32; j++) {
|
|
|
|
|
if (role & (1u << j)) {
|
|
|
|
|
char reasonbuf[OFP_ASYNC_CONFIG_REASON_BUFSIZE];
|
ofproto: Implement OF1.4 Set/Get asynchronous configuration messages.
This patch adds support for Openflow1.4 set/get asynchronous configuration
messages. OpenVSwitch already supports set/get asynchronous configuration
messages for Openflow1.3. In this patch OFPT_SET_ASYNC_CONFIG message
allows the controllers to set the configuration for OFPT_ROLE_STATUS,
OFPT_TABLE_STATUS and OFPT_REQUESTFORWARD in addition to the Openflow1.3
messages. In a OFPT_SET_ASYNC, only the properties that shall be changed
need to be included, properties that are omitted from the message are
unchanged.
The OFPT_GET_ASYNC_CONFIG is used to query the asynchronous configuration
of switch. In a OFPT_GET_ASYNC_REPLY message, all properties must be
included.
According to Openflow1.4 the initial configuration shall be:
- In the “master” or “equal” role, enable all OFPT_PACKET_IN messages,
except those with reason OFPR_INVALID_TTL, enable all OFPT_PORT_STATUS
and OFPT_FLOW_REMOVED messages, and disable all OFPT_ROLE_STATUS,
OFPT_TABLE_STATUS and OFPT_REQUESTFORWARD messages.
- In the “slave” role, enable all OFPT_PORT_STATUS messages and disable
all OFPT_PACKET_IN, OFPT_FLOW_REMOVED, OFPT_ROLE_STATUS,
OFPT_TABLE_STATUS and OFPT_REQUESTFORWARD messages.
Signed-off-by: Niti Rohilla <niti.rohilla@tcs.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
2015-07-23 17:05:44 +05:30
|
|
|
|
const char *reason;
|
2013-06-12 14:49:19 -07:00
|
|
|
|
|
2016-01-14 22:16:34 -08:00
|
|
|
|
reason = ofp_async_config_reason_to_string(
|
|
|
|
|
j, type, reasonbuf, sizeof reasonbuf);
|
openflow: Better abstract handling of packet-in messages.
Packet-in messages have been a bit of a mess. First, their abstraction
in the form of struct ofputil_packet_in has some fields that are used
in a clear way for incoming and outgoing packet-ins, and others
(packet_len, total_len, buffer_id) have have confusing meanings or
usage pattern depending on their direction.
Second, it's very confusing how a packet-in has both a reason (OFPR_*)
and a miss type (OFPROTO_PACKET_IN_*) and how those add up to the
actual reason that is used "on the wire" for each OpenFlow version (and
even whether the packet-in is sent at all!).
Finally, there's all kind of low-level detail randomly scattered between
connmgr, ofproto-dpif-xlate, and ofp-util.
This commit attempts to clear up some of the confusion. It simplifies
the struct ofputil_packet_in abstraction by removing the members that
didn't have a clear and consistent meaning between incoming and outgoing
packet-ins. It gets rid of OFPROTO_PACKET_IN_*, instead adding a couple
of nonstandard OFPR_* reasons that add up to what OFPROTO_PACKET_IN_*
was meant to say (in what I hope is a clearer way). And it consolidates
the tricky parts into ofp-util, where I hope it will be easier to
understand all in one place.
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Jarno Rajahalme <jarno@ovn.org>
2016-01-20 09:57:16 -08:00
|
|
|
|
if (reason[0]) {
|
|
|
|
|
ds_put_format(string, " %s", reason);
|
|
|
|
|
}
|
ofproto: Implement OF1.4 Set/Get asynchronous configuration messages.
This patch adds support for Openflow1.4 set/get asynchronous configuration
messages. OpenVSwitch already supports set/get asynchronous configuration
messages for Openflow1.3. In this patch OFPT_SET_ASYNC_CONFIG message
allows the controllers to set the configuration for OFPT_ROLE_STATUS,
OFPT_TABLE_STATUS and OFPT_REQUESTFORWARD in addition to the Openflow1.3
messages. In a OFPT_SET_ASYNC, only the properties that shall be changed
need to be included, properties that are omitted from the message are
unchanged.
The OFPT_GET_ASYNC_CONFIG is used to query the asynchronous configuration
of switch. In a OFPT_GET_ASYNC_REPLY message, all properties must be
included.
According to Openflow1.4 the initial configuration shall be:
- In the “master” or “equal” role, enable all OFPT_PACKET_IN messages,
except those with reason OFPR_INVALID_TTL, enable all OFPT_PORT_STATUS
and OFPT_FLOW_REMOVED messages, and disable all OFPT_ROLE_STATUS,
OFPT_TABLE_STATUS and OFPT_REQUESTFORWARD messages.
- In the “slave” role, enable all OFPT_PORT_STATUS messages and disable
all OFPT_PACKET_IN, OFPT_FLOW_REMOVED, OFPT_ROLE_STATUS,
OFPT_TABLE_STATUS and OFPT_REQUESTFORWARD messages.
Signed-off-by: Niti Rohilla <niti.rohilla@tcs.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
2015-07-23 17:05:44 +05:30
|
|
|
|
}
|
2012-02-09 14:06:35 -08:00
|
|
|
|
}
|
2016-01-14 22:16:34 -08:00
|
|
|
|
if (!role) {
|
ofproto: Implement OF1.4 Set/Get asynchronous configuration messages.
This patch adds support for Openflow1.4 set/get asynchronous configuration
messages. OpenVSwitch already supports set/get asynchronous configuration
messages for Openflow1.3. In this patch OFPT_SET_ASYNC_CONFIG message
allows the controllers to set the configuration for OFPT_ROLE_STATUS,
OFPT_TABLE_STATUS and OFPT_REQUESTFORWARD in addition to the Openflow1.3
messages. In a OFPT_SET_ASYNC, only the properties that shall be changed
need to be included, properties that are omitted from the message are
unchanged.
The OFPT_GET_ASYNC_CONFIG is used to query the asynchronous configuration
of switch. In a OFPT_GET_ASYNC_REPLY message, all properties must be
included.
According to Openflow1.4 the initial configuration shall be:
- In the “master” or “equal” role, enable all OFPT_PACKET_IN messages,
except those with reason OFPR_INVALID_TTL, enable all OFPT_PORT_STATUS
and OFPT_FLOW_REMOVED messages, and disable all OFPT_ROLE_STATUS,
OFPT_TABLE_STATUS and OFPT_REQUESTFORWARD messages.
- In the “slave” role, enable all OFPT_PORT_STATUS messages and disable
all OFPT_PACKET_IN, OFPT_FLOW_REMOVED, OFPT_ROLE_STATUS,
OFPT_TABLE_STATUS and OFPT_REQUESTFORWARD messages.
Signed-off-by: Niti Rohilla <niti.rohilla@tcs.com>
Signed-off-by: Ben Pfaff <blp@nicira.com>
2015-07-23 17:05:44 +05:30
|
|
|
|
ds_put_cstr(string, " (off)");
|
|
|
|
|
}
|
|
|
|
|
ds_put_char(string, '\n');
|
2012-02-09 14:06:35 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-01-04 22:40:01 -08:00
|
|
|
|
|
|
|
|
|
return 0;
|
2012-02-09 14:06:35 -08:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2012-02-09 14:17:33 -08:00
|
|
|
|
ofp_print_nxt_set_controller_id(struct ds *string,
|
|
|
|
|
const struct nx_controller_id *nci)
|
|
|
|
|
{
|
|
|
|
|
ds_put_format(string, " id=%"PRIu16, ntohs(nci->controller_id));
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return 0;
|
2012-02-09 14:17:33 -08:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2012-07-12 14:18:05 -07:00
|
|
|
|
ofp_print_nxt_flow_monitor_cancel(struct ds *string,
|
|
|
|
|
const struct ofp_header *oh)
|
|
|
|
|
{
|
|
|
|
|
ds_put_format(string, " id=%"PRIu32,
|
|
|
|
|
ofputil_decode_flow_monitor_cancel(oh));
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return 0;
|
2012-07-12 14:18:05 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
|
nx_flow_monitor_flags_to_name(uint32_t bit)
|
|
|
|
|
{
|
|
|
|
|
enum nx_flow_monitor_flags fmf = bit;
|
|
|
|
|
|
|
|
|
|
switch (fmf) {
|
|
|
|
|
case NXFMF_INITIAL: return "initial";
|
|
|
|
|
case NXFMF_ADD: return "add";
|
|
|
|
|
case NXFMF_DELETE: return "delete";
|
|
|
|
|
case NXFMF_MODIFY: return "modify";
|
|
|
|
|
case NXFMF_ACTIONS: return "actions";
|
|
|
|
|
case NXFMF_OWN: return "own";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2012-07-12 14:18:05 -07:00
|
|
|
|
ofp_print_nxst_flow_monitor_request(struct ds *string,
|
2017-05-31 16:06:12 -07:00
|
|
|
|
const struct ofp_header *oh,
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
const struct ofputil_port_map *port_map,
|
|
|
|
|
const struct ofputil_table_map *table_map)
|
2012-07-12 14:18:05 -07:00
|
|
|
|
{
|
2016-02-18 15:13:09 -08:00
|
|
|
|
struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
|
2012-07-12 14:18:05 -07:00
|
|
|
|
for (;;) {
|
|
|
|
|
struct ofputil_flow_monitor_request request;
|
|
|
|
|
int retval;
|
|
|
|
|
|
|
|
|
|
retval = ofputil_decode_flow_monitor_request(&request, &b);
|
|
|
|
|
if (retval) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return retval != EOF ? retval : 0;
|
2012-07-12 14:18:05 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ds_put_format(string, "\n id=%"PRIu32" flags=", request.id);
|
|
|
|
|
ofp_print_bit_names(string, request.flags,
|
|
|
|
|
nx_flow_monitor_flags_to_name, ',');
|
|
|
|
|
|
|
|
|
|
if (request.out_port != OFPP_NONE) {
|
|
|
|
|
ds_put_cstr(string, " out_port=");
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ofputil_format_port(request.out_port, port_map, string);
|
2012-07-12 14:18:05 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (request.table_id != 0xff) {
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
ds_put_format(string, " table=");
|
|
|
|
|
ofputil_format_table(request.table_id, table_map, string);
|
2012-07-12 14:18:05 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ds_put_char(string, ' ');
|
2017-05-31 16:06:12 -07:00
|
|
|
|
match_format(&request.match, port_map, string, OFP_DEFAULT_PRIORITY);
|
2012-07-12 14:18:05 -07:00
|
|
|
|
ds_chomp(string, ' ');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2012-07-12 14:18:05 -07:00
|
|
|
|
ofp_print_nxst_flow_monitor_reply(struct ds *string,
|
2017-05-31 16:06:12 -07:00
|
|
|
|
const struct ofp_header *oh,
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
const struct ofputil_port_map *port_map,
|
|
|
|
|
const struct ofputil_table_map *table_map)
|
2012-07-12 14:18:05 -07:00
|
|
|
|
{
|
|
|
|
|
uint64_t ofpacts_stub[1024 / 8];
|
2016-02-18 15:13:09 -08:00
|
|
|
|
struct ofpbuf ofpacts = OFPBUF_STUB_INITIALIZER(ofpacts_stub);
|
|
|
|
|
struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
|
2012-07-12 14:18:05 -07:00
|
|
|
|
|
|
|
|
|
for (;;) {
|
2013-06-12 14:49:19 -07:00
|
|
|
|
char reasonbuf[OFP_FLOW_REMOVED_REASON_BUFSIZE];
|
2012-07-12 14:18:05 -07:00
|
|
|
|
struct ofputil_flow_update update;
|
|
|
|
|
int retval;
|
|
|
|
|
|
|
|
|
|
retval = ofputil_decode_flow_update(&update, &b, &ofpacts);
|
|
|
|
|
if (retval) {
|
|
|
|
|
ofpbuf_uninit(&ofpacts);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return retval != EOF ? retval : 0;
|
2012-07-12 14:18:05 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ds_put_cstr(string, "\n event=");
|
|
|
|
|
switch (update.event) {
|
|
|
|
|
case NXFME_ADDED:
|
|
|
|
|
ds_put_cstr(string, "ADDED");
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case NXFME_DELETED:
|
|
|
|
|
ds_put_format(string, "DELETED reason=%s",
|
2013-06-12 14:49:19 -07:00
|
|
|
|
ofp_flow_removed_reason_to_string(update.reason,
|
|
|
|
|
reasonbuf,
|
|
|
|
|
sizeof reasonbuf));
|
2012-07-12 14:18:05 -07:00
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case NXFME_MODIFIED:
|
|
|
|
|
ds_put_cstr(string, "MODIFIED");
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case NXFME_ABBREV:
|
|
|
|
|
ds_put_format(string, "ABBREV xid=0x%"PRIx32, ntohl(update.xid));
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
ds_put_format(string, " table=");
|
|
|
|
|
ofputil_format_table(update.table_id, table_map, string);
|
2012-07-12 14:18:05 -07:00
|
|
|
|
if (update.idle_timeout != OFP_FLOW_PERMANENT) {
|
|
|
|
|
ds_put_format(string, " idle_timeout=%"PRIu16,
|
|
|
|
|
update.idle_timeout);
|
|
|
|
|
}
|
|
|
|
|
if (update.hard_timeout != OFP_FLOW_PERMANENT) {
|
|
|
|
|
ds_put_format(string, " hard_timeout=%"PRIu16,
|
|
|
|
|
update.hard_timeout);
|
|
|
|
|
}
|
|
|
|
|
ds_put_format(string, " cookie=%#"PRIx64, ntohll(update.cookie));
|
|
|
|
|
|
|
|
|
|
ds_put_char(string, ' ');
|
2017-05-31 16:06:12 -07:00
|
|
|
|
match_format(&update.match, port_map, string, OFP_DEFAULT_PRIORITY);
|
2012-07-12 14:18:05 -07:00
|
|
|
|
|
|
|
|
|
if (update.ofpacts_len) {
|
|
|
|
|
if (string->string[string->length - 1] != ' ') {
|
|
|
|
|
ds_put_char(string, ' ');
|
|
|
|
|
}
|
2013-10-14 14:08:20 -07:00
|
|
|
|
ds_put_cstr(string, "actions=");
|
2018-01-12 12:56:12 -08:00
|
|
|
|
struct ofpact_format_params fp = {
|
|
|
|
|
.port_map = port_map,
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
.table_map = table_map,
|
2018-01-12 12:56:12 -08:00
|
|
|
|
.s = string,
|
|
|
|
|
};
|
|
|
|
|
ofpacts_format(update.ofpacts, update.ofpacts_len, &fp);
|
2012-07-12 14:18:05 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-07-12 13:32:47 -07:00
|
|
|
|
void
|
|
|
|
|
ofp_print_version(const struct ofp_header *oh,
|
|
|
|
|
struct ds *string)
|
2010-12-06 10:20:20 -08:00
|
|
|
|
{
|
2012-02-15 15:28:25 -08:00
|
|
|
|
switch (oh->version) {
|
|
|
|
|
case OFP10_VERSION:
|
|
|
|
|
break;
|
|
|
|
|
case OFP11_VERSION:
|
|
|
|
|
ds_put_cstr(string, " (OF1.1)");
|
2012-06-27 17:19:52 +09:00
|
|
|
|
break;
|
|
|
|
|
case OFP12_VERSION:
|
|
|
|
|
ds_put_cstr(string, " (OF1.2)");
|
2012-02-15 15:28:25 -08:00
|
|
|
|
break;
|
2012-11-27 17:44:22 +02:00
|
|
|
|
case OFP13_VERSION:
|
|
|
|
|
ds_put_cstr(string, " (OF1.3)");
|
|
|
|
|
break;
|
2014-05-01 13:22:20 +03:00
|
|
|
|
case OFP14_VERSION:
|
|
|
|
|
ds_put_cstr(string, " (OF1.4)");
|
|
|
|
|
break;
|
2014-05-07 13:42:24 -07:00
|
|
|
|
case OFP15_VERSION:
|
|
|
|
|
ds_put_cstr(string, " (OF1.5)");
|
|
|
|
|
break;
|
2016-04-10 14:39:12 -07:00
|
|
|
|
case OFP16_VERSION:
|
|
|
|
|
ds_put_cstr(string, " (OF1.6)");
|
|
|
|
|
break;
|
2012-02-15 15:28:25 -08:00
|
|
|
|
default:
|
|
|
|
|
ds_put_format(string, " (OF 0x%02"PRIx8")", oh->version);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
ds_put_format(string, " (xid=0x%"PRIx32"):", ntohl(oh->xid));
|
2012-07-12 13:32:47 -07:00
|
|
|
|
}
|
2010-12-06 10:20:20 -08:00
|
|
|
|
|
2012-05-23 09:33:22 -07:00
|
|
|
|
static void
|
2012-07-19 23:23:17 -07:00
|
|
|
|
ofp_header_to_string__(const struct ofp_header *oh, enum ofpraw raw,
|
|
|
|
|
struct ds *string)
|
2012-05-23 09:33:22 -07:00
|
|
|
|
{
|
2012-07-19 23:23:17 -07:00
|
|
|
|
ds_put_cstr(string, ofpraw_get_name(raw));
|
2012-05-23 09:33:22 -07:00
|
|
|
|
ofp_print_version(oh, string);
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-11 12:39:20 +09:00
|
|
|
|
static void
|
2014-11-11 12:39:21 +09:00
|
|
|
|
ofp_print_bucket_id(struct ds *s, const char *label, uint32_t bucket_id,
|
2014-11-11 12:39:20 +09:00
|
|
|
|
enum ofp_version ofp_version)
|
|
|
|
|
{
|
|
|
|
|
if (ofp_version < OFP15_VERSION) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-11 12:39:21 +09:00
|
|
|
|
ds_put_cstr(s, label);
|
2014-11-11 12:39:20 +09:00
|
|
|
|
|
|
|
|
|
switch (bucket_id) {
|
|
|
|
|
case OFPG15_BUCKET_FIRST:
|
|
|
|
|
ds_put_cstr(s, "first");
|
|
|
|
|
break;
|
|
|
|
|
case OFPG15_BUCKET_LAST:
|
|
|
|
|
ds_put_cstr(s, "last");
|
|
|
|
|
break;
|
|
|
|
|
case OFPG15_BUCKET_ALL:
|
|
|
|
|
ds_put_cstr(s, "all");
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
ds_put_format(s, "%"PRIu32, bucket_id);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ds_put_char(s, ',');
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-01 18:30:17 -07:00
|
|
|
|
static void
|
|
|
|
|
ofp_print_group(struct ds *s, uint32_t group_id, uint8_t type,
|
2015-09-09 17:33:42 +05:30
|
|
|
|
const struct ovs_list *p_buckets,
|
|
|
|
|
const struct ofputil_group_props *props,
|
2017-05-31 16:06:12 -07:00
|
|
|
|
enum ofp_version ofp_version, bool suppress_type,
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
const struct ofputil_port_map *port_map,
|
|
|
|
|
const struct ofputil_table_map *table_map)
|
2013-09-01 18:30:17 -07:00
|
|
|
|
{
|
|
|
|
|
struct ofputil_bucket *bucket;
|
|
|
|
|
|
2014-11-11 12:39:21 +09:00
|
|
|
|
ds_put_format(s, "group_id=%"PRIu32, group_id);
|
|
|
|
|
|
|
|
|
|
if (!suppress_type) {
|
|
|
|
|
static const char *type_str[] = { "all", "select", "indirect",
|
|
|
|
|
"ff", "unknown" };
|
|
|
|
|
ds_put_format(s, ",type=%s", type_str[type > 4 ? 4 : type]);
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-20 13:50:31 +09:00
|
|
|
|
if (props->selection_method[0]) {
|
ofp-parse: Fix parsing, formatting of multiple fields in NTR extension.
Until now, the only way to specify multiple fields in the "fields"
parameter for the Netronome groups extension, was to specify "fields"
more than once, e.g. fields=eth_dst,fields=ip_dst
However, this wasn't documented and the code in ofp-print didn't use it,
generating output that couldn't be parsed.
This commit fixes the situation by introducing a more straightforward
syntax, e.g. fields(eth_dst,ip_dst), documents it, and adjusts ofp-print
code to use it when there is more than one field (it retains the previous
format for backward compatibility when there is exactly one field)
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Simon Horman <simon.horman@netronome.com>
2015-10-15 09:46:21 -07:00
|
|
|
|
ds_put_format(s, ",selection_method=%s", props->selection_method);
|
2015-03-20 13:50:31 +09:00
|
|
|
|
if (props->selection_method_param) {
|
ofp-parse: Fix parsing, formatting of multiple fields in NTR extension.
Until now, the only way to specify multiple fields in the "fields"
parameter for the Netronome groups extension, was to specify "fields"
more than once, e.g. fields=eth_dst,fields=ip_dst
However, this wasn't documented and the code in ofp-print didn't use it,
generating output that couldn't be parsed.
This commit fixes the situation by introducing a more straightforward
syntax, e.g. fields(eth_dst,ip_dst), documents it, and adjusts ofp-print
code to use it when there is more than one field (it retains the previous
format for backward compatibility when there is exactly one field)
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Simon Horman <simon.horman@netronome.com>
2015-10-15 09:46:21 -07:00
|
|
|
|
ds_put_format(s, ",selection_method_param=%"PRIu64,
|
2015-03-20 13:50:31 +09:00
|
|
|
|
props->selection_method_param);
|
|
|
|
|
}
|
|
|
|
|
|
ofp-parse: Fix parsing, formatting of multiple fields in NTR extension.
Until now, the only way to specify multiple fields in the "fields"
parameter for the Netronome groups extension, was to specify "fields"
more than once, e.g. fields=eth_dst,fields=ip_dst
However, this wasn't documented and the code in ofp-print didn't use it,
generating output that couldn't be parsed.
This commit fixes the situation by introducing a more straightforward
syntax, e.g. fields(eth_dst,ip_dst), documents it, and adjusts ofp-print
code to use it when there is more than one field (it retains the previous
format for backward compatibility when there is exactly one field)
Signed-off-by: Ben Pfaff <blp@nicira.com>
Acked-by: Simon Horman <simon.horman@netronome.com>
2015-10-15 09:46:21 -07:00
|
|
|
|
size_t n = bitmap_count1(props->fields.used.bm, MFF_N_IDS);
|
|
|
|
|
if (n == 1) {
|
|
|
|
|
ds_put_cstr(s, ",fields=");
|
|
|
|
|
oxm_format_field_array(s, &props->fields);
|
|
|
|
|
} else if (n > 1) {
|
|
|
|
|
ds_put_cstr(s, ",fields(");
|
|
|
|
|
oxm_format_field_array(s, &props->fields);
|
|
|
|
|
ds_put_char(s, ')');
|
2015-03-20 13:50:31 +09:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-01 18:30:17 -07:00
|
|
|
|
if (!p_buckets) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-11 12:39:21 +09:00
|
|
|
|
ds_put_char(s, ',');
|
|
|
|
|
|
2013-09-01 18:30:17 -07:00
|
|
|
|
LIST_FOR_EACH (bucket, list_node, p_buckets) {
|
2014-11-11 12:39:21 +09:00
|
|
|
|
ds_put_cstr(s, "bucket=");
|
2013-09-01 18:30:17 -07:00
|
|
|
|
|
2014-11-11 12:39:21 +09:00
|
|
|
|
ofp_print_bucket_id(s, "bucket_id:", bucket->bucket_id, ofp_version);
|
2015-07-28 22:01:24 -07:00
|
|
|
|
if (bucket->weight != (type == OFPGT11_SELECT ? 1 : 0)) {
|
2013-09-01 18:30:17 -07:00
|
|
|
|
ds_put_format(s, "weight:%"PRIu16",", bucket->weight);
|
|
|
|
|
}
|
|
|
|
|
if (bucket->watch_port != OFPP_NONE) {
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ds_put_cstr(s, "watch_port:");
|
|
|
|
|
ofputil_format_port(bucket->watch_port, port_map, s);
|
|
|
|
|
ds_put_char(s, ',');
|
2013-09-01 18:30:17 -07:00
|
|
|
|
}
|
2015-11-24 10:01:23 -08:00
|
|
|
|
if (bucket->watch_group != OFPG_ANY) {
|
2013-09-01 18:30:17 -07:00
|
|
|
|
ds_put_format(s, "watch_group:%"PRIu32",", bucket->watch_group);
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-14 14:08:20 -07:00
|
|
|
|
ds_put_cstr(s, "actions=");
|
2018-01-12 12:56:12 -08:00
|
|
|
|
struct ofpact_format_params fp = {
|
|
|
|
|
.port_map = port_map,
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
.table_map = table_map,
|
2018-01-12 12:56:12 -08:00
|
|
|
|
.s = s,
|
|
|
|
|
};
|
|
|
|
|
ofpacts_format(bucket->ofpacts, bucket->ofpacts_len, &fp);
|
2014-11-11 12:39:21 +09:00
|
|
|
|
ds_put_char(s, ',');
|
2013-09-01 18:30:17 -07:00
|
|
|
|
}
|
2014-11-11 12:39:21 +09:00
|
|
|
|
|
|
|
|
|
ds_chomp(s, ',');
|
2013-09-01 18:30:17 -07:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2014-05-07 23:49:00 -07:00
|
|
|
|
ofp_print_ofpst_group_desc_request(struct ds *string,
|
|
|
|
|
const struct ofp_header *oh)
|
|
|
|
|
{
|
|
|
|
|
uint32_t group_id = ofputil_decode_group_desc_request(oh);
|
|
|
|
|
ds_put_cstr(string, " group_id=");
|
|
|
|
|
ofputil_format_group(group_id, string);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
|
|
|
|
|
return 0;
|
2014-05-07 23:49:00 -07:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ofp_print_group_desc(struct ds *s, const struct ofp_header *oh,
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
const struct ofputil_port_map *port_map,
|
|
|
|
|
const struct ofputil_table_map *table_map)
|
2013-09-01 18:30:17 -07:00
|
|
|
|
{
|
2016-02-18 15:13:09 -08:00
|
|
|
|
struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
|
2013-09-01 18:30:17 -07:00
|
|
|
|
for (;;) {
|
|
|
|
|
struct ofputil_group_desc gd;
|
|
|
|
|
int retval;
|
|
|
|
|
|
2013-10-17 10:15:08 +09:00
|
|
|
|
retval = ofputil_decode_group_desc_reply(&gd, &b, oh->version);
|
2013-09-01 18:30:17 -07:00
|
|
|
|
if (retval) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return retval != EOF ? retval : 0;
|
2013-09-01 18:30:17 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ds_put_char(s, '\n');
|
|
|
|
|
ds_put_char(s, ' ');
|
2015-03-20 13:50:31 +09:00
|
|
|
|
ofp_print_group(s, gd.group_id, gd.type, &gd.buckets, &gd.props,
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
oh->version, false, port_map, table_map);
|
2016-07-29 16:52:04 -07:00
|
|
|
|
ofputil_uninit_group_desc(&gd);
|
2013-09-01 18:30:17 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2013-09-01 18:30:17 -07:00
|
|
|
|
ofp_print_ofpst_group_request(struct ds *string, const struct ofp_header *oh)
|
|
|
|
|
{
|
|
|
|
|
enum ofperr error;
|
|
|
|
|
uint32_t group_id;
|
|
|
|
|
|
|
|
|
|
error = ofputil_decode_group_stats_request(oh, &group_id);
|
|
|
|
|
if (error) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return error;
|
2013-09-01 18:30:17 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ds_put_cstr(string, " group_id=");
|
|
|
|
|
ofputil_format_group(group_id, string);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return 0;
|
2013-09-01 18:30:17 -07:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2013-09-01 18:30:17 -07:00
|
|
|
|
ofp_print_group_stats(struct ds *s, const struct ofp_header *oh)
|
|
|
|
|
{
|
2016-02-18 15:13:09 -08:00
|
|
|
|
struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
|
2013-09-01 18:30:17 -07:00
|
|
|
|
for (;;) {
|
|
|
|
|
struct ofputil_group_stats gs;
|
|
|
|
|
int retval;
|
|
|
|
|
|
|
|
|
|
retval = ofputil_decode_group_stats_reply(&b, &gs);
|
|
|
|
|
if (retval) {
|
|
|
|
|
if (retval != EOF) {
|
|
|
|
|
ds_put_cstr(s, " ***parse error***");
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return retval;
|
2013-09-01 18:30:17 -07:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ds_put_char(s, '\n');
|
|
|
|
|
|
|
|
|
|
ds_put_char(s, ' ');
|
|
|
|
|
ds_put_format(s, "group_id=%"PRIu32",", gs.group_id);
|
|
|
|
|
|
|
|
|
|
if (gs.duration_sec != UINT32_MAX) {
|
|
|
|
|
ds_put_cstr(s, "duration=");
|
|
|
|
|
ofp_print_duration(s, gs.duration_sec, gs.duration_nsec);
|
|
|
|
|
ds_put_char(s, ',');
|
|
|
|
|
}
|
|
|
|
|
ds_put_format(s, "ref_count=%"PRIu32",", gs.ref_count);
|
|
|
|
|
ds_put_format(s, "packet_count=%"PRIu64",", gs.packet_count);
|
|
|
|
|
ds_put_format(s, "byte_count=%"PRIu64"", gs.byte_count);
|
|
|
|
|
|
2016-02-18 15:13:09 -08:00
|
|
|
|
for (uint32_t bucket_i = 0; bucket_i < gs.n_buckets; bucket_i++) {
|
2013-09-01 18:30:17 -07:00
|
|
|
|
if (gs.bucket_stats[bucket_i].packet_count != UINT64_MAX) {
|
|
|
|
|
ds_put_format(s, ",bucket%"PRIu32":", bucket_i);
|
|
|
|
|
ds_put_format(s, "packet_count=%"PRIu64",", gs.bucket_stats[bucket_i].packet_count);
|
|
|
|
|
ds_put_format(s, "byte_count=%"PRIu64"", gs.bucket_stats[bucket_i].byte_count);
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-09-05 14:19:13 +09:00
|
|
|
|
|
|
|
|
|
free(gs.bucket_stats);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
}
|
|
|
|
|
return 0;
|
2013-09-01 18:30:17 -07:00
|
|
|
|
}
|
|
|
|
|
|
2014-08-11 10:57:03 -07:00
|
|
|
|
static const char *
|
|
|
|
|
group_type_to_string(enum ofp11_group_type type)
|
|
|
|
|
{
|
|
|
|
|
switch (type) {
|
|
|
|
|
case OFPGT11_ALL: return "all";
|
|
|
|
|
case OFPGT11_SELECT: return "select";
|
|
|
|
|
case OFPGT11_INDIRECT: return "indirect";
|
|
|
|
|
case OFPGT11_FF: return "fast failover";
|
|
|
|
|
default: OVS_NOT_REACHED();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2013-09-01 18:30:17 -07:00
|
|
|
|
ofp_print_group_features(struct ds *string, const struct ofp_header *oh)
|
|
|
|
|
{
|
|
|
|
|
struct ofputil_group_features features;
|
2014-08-11 10:57:03 -07:00
|
|
|
|
int i;
|
2013-09-01 18:30:17 -07:00
|
|
|
|
|
|
|
|
|
ofputil_decode_group_features_reply(oh, &features);
|
|
|
|
|
|
|
|
|
|
ds_put_format(string, "\n Group table:\n");
|
|
|
|
|
ds_put_format(string, " Types: 0x%"PRIx32"\n", features.types);
|
|
|
|
|
ds_put_format(string, " Capabilities: 0x%"PRIx32"\n",
|
|
|
|
|
features.capabilities);
|
|
|
|
|
|
2014-08-11 10:57:03 -07:00
|
|
|
|
for (i = 0; i < OFPGT12_N_TYPES; i++) {
|
|
|
|
|
if (features.types & (1u << i)) {
|
|
|
|
|
ds_put_format(string, " %s group:\n", group_type_to_string(i));
|
|
|
|
|
ds_put_format(string, " max_groups=%#"PRIx32"\n",
|
|
|
|
|
features.max_groups[i]);
|
|
|
|
|
ds_put_format(string, " actions: ");
|
|
|
|
|
ofpact_bitmap_format(features.ofpacts[i], string);
|
|
|
|
|
ds_put_char(string, '\n');
|
|
|
|
|
}
|
2013-09-01 18:30:17 -07:00
|
|
|
|
}
|
2018-01-04 22:40:01 -08:00
|
|
|
|
|
|
|
|
|
return 0;
|
2013-09-01 18:30:17 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2015-09-09 17:33:42 +05:30
|
|
|
|
ofp_print_group_mod__(struct ds *s, enum ofp_version ofp_version,
|
2017-05-31 16:06:12 -07:00
|
|
|
|
const struct ofputil_group_mod *gm,
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
const struct ofputil_port_map *port_map,
|
|
|
|
|
const struct ofputil_table_map *table_map)
|
2013-09-01 18:30:17 -07:00
|
|
|
|
{
|
2014-11-11 12:39:21 +09:00
|
|
|
|
bool bucket_command = false;
|
2013-09-01 18:30:17 -07:00
|
|
|
|
|
|
|
|
|
ds_put_char(s, '\n');
|
|
|
|
|
|
|
|
|
|
ds_put_char(s, ' ');
|
2015-09-09 17:33:42 +05:30
|
|
|
|
switch (gm->command) {
|
2013-09-01 18:30:17 -07:00
|
|
|
|
case OFPGC11_ADD:
|
|
|
|
|
ds_put_cstr(s, "ADD");
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case OFPGC11_MODIFY:
|
|
|
|
|
ds_put_cstr(s, "MOD");
|
|
|
|
|
break;
|
|
|
|
|
|
ofproto: Add relaxed group_mod command ADD_OR_MOD
This patch adds support for a new Group Mod command OFPGC_ADD_OR_MOD to
OVS for all OpenFlow versions that support groups (OF11 and higher).
The new ADD_OR_MOD creates a group that does not yet exist (like ADD)
and modifies an existing group (like MODIFY).
Rational: In OpenFlow 1.x the Group Mod commands OFPGC_ADD and
OFPGC_MODIFY have strict semantics: ADD fails if the group exists,
while MODIFY fails if the group does not exist. This requires a
controller to exactly know the state of the switch when programming a
group in order not run the risk of getting an OFP Error message in
response. This is hard to achieve and maintain at all times in view of
possible switch and controller restarts or other connection losses
between switch and controller.
Due to the un-acknowledged nature of the Group Mod message programming
groups safely and efficiently at the same time is virtually impossible
as the controller has to either query the existence of the group prior
to each Group Mod message or to insert a Barrier Request/Reply after
every group to be sure that no Error can be received at a later stage
and require a complicated roll-back of any dependent actions taken
between the failed Group Mod and the Error.
In the ovs-ofctl command line the ADD_OR_MOD command is made available
through the new option --may-create in the mod-group command:
$ ovs-ofctl -Oopenflow13 del-groups br-int group_id=100
$ ovs-ofctl -Oopenflow13 mod-group br-int
group_id=100,type=indirect,bucket=actions=2 OFPT_ERROR (OF1.3)
(xid=0x2): OFPGMFC_UNKNOWN_GROUP OFPT_GROUP_MOD (OF1.3) (xid=0x2):
MOD group_id=100,type=indirect,bucket=actions=output:2
$ ovs-ofctl -Oopenflow13 --may-create mod-group br-int
group_id=100,type=indirect,bucket=actions=2
$ ovs-ofctl -Oopenflow13 dump-groups br-int
OFPST_GROUP_DESC reply (OF1.3) (xid=0x2):
group_id=100,type=indirect,bucket=actions=output:2
$ ovs-ofctl -Oopenflow13 --may-create mod-group br-int
group_id=100,type=indirect,bucket=actions=3
$ ovs-ofctl -Oopenflow13 dump-groups br-int
OFPST_GROUP_DESC reply (OF1.3) (xid=0x2):
group_id=100,type=indirect,bucket=actions=output:3
Signed-off-by: Jan Scheurich <jan.scheurich at web.de>
Signed-off-by: Ben Pfaff <blp@ovn.org>
2016-06-29 00:29:25 +02:00
|
|
|
|
case OFPGC11_ADD_OR_MOD:
|
|
|
|
|
ds_put_cstr(s, "ADD_OR_MOD");
|
|
|
|
|
break;
|
|
|
|
|
|
2013-09-01 18:30:17 -07:00
|
|
|
|
case OFPGC11_DELETE:
|
|
|
|
|
ds_put_cstr(s, "DEL");
|
|
|
|
|
break;
|
|
|
|
|
|
2014-11-11 12:39:21 +09:00
|
|
|
|
case OFPGC15_INSERT_BUCKET:
|
|
|
|
|
ds_put_cstr(s, "INSERT_BUCKET");
|
|
|
|
|
bucket_command = true;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case OFPGC15_REMOVE_BUCKET:
|
|
|
|
|
ds_put_cstr(s, "REMOVE_BUCKET");
|
|
|
|
|
bucket_command = true;
|
|
|
|
|
break;
|
|
|
|
|
|
2013-09-01 18:30:17 -07:00
|
|
|
|
default:
|
2015-09-09 17:33:42 +05:30
|
|
|
|
ds_put_format(s, "cmd:%"PRIu16"", gm->command);
|
2013-09-01 18:30:17 -07:00
|
|
|
|
}
|
|
|
|
|
ds_put_char(s, ' ');
|
|
|
|
|
|
2014-11-11 12:39:21 +09:00
|
|
|
|
if (bucket_command) {
|
|
|
|
|
ofp_print_bucket_id(s, "command_bucket_id:",
|
2015-09-09 17:33:42 +05:30
|
|
|
|
gm->command_bucket_id, ofp_version);
|
2014-11-11 12:39:21 +09:00
|
|
|
|
}
|
|
|
|
|
|
2015-09-09 17:33:42 +05:30
|
|
|
|
ofp_print_group(s, gm->group_id, gm->type, &gm->buckets, &gm->props,
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
ofp_version, bucket_command, port_map, table_map);
|
2015-09-09 17:33:42 +05:30
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ofp_print_group_mod(struct ds *s, const struct ofp_header *oh,
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
const struct ofputil_port_map *port_map,
|
|
|
|
|
const struct ofputil_table_map *table_map)
|
2015-09-09 17:33:42 +05:30
|
|
|
|
{
|
|
|
|
|
struct ofputil_group_mod gm;
|
|
|
|
|
int error;
|
|
|
|
|
|
|
|
|
|
error = ofputil_decode_group_mod(oh, &gm);
|
|
|
|
|
if (error) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return error;
|
2015-09-09 17:33:42 +05:30
|
|
|
|
}
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
ofp_print_group_mod__(s, oh->version, &gm, port_map, table_map);
|
2016-07-29 16:52:04 -07:00
|
|
|
|
ofputil_uninit_group_mod(&gm);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return 0;
|
2013-09-01 18:30:17 -07:00
|
|
|
|
}
|
|
|
|
|
|
2014-03-23 23:20:04 -07:00
|
|
|
|
static void
|
|
|
|
|
print_table_action_features(struct ds *s,
|
|
|
|
|
const struct ofputil_table_action_features *taf)
|
|
|
|
|
{
|
2014-08-11 11:31:45 -07:00
|
|
|
|
if (taf->ofpacts) {
|
|
|
|
|
ds_put_cstr(s, " actions: ");
|
|
|
|
|
ofpact_bitmap_format(taf->ofpacts, s);
|
|
|
|
|
ds_put_char(s, '\n');
|
|
|
|
|
}
|
2014-03-23 23:20:04 -07:00
|
|
|
|
|
2014-07-26 12:15:26 -07:00
|
|
|
|
if (!bitmap_is_all_zeros(taf->set_fields.bm, MFF_N_IDS)) {
|
2014-03-23 23:20:04 -07:00
|
|
|
|
int i;
|
|
|
|
|
|
2014-08-11 11:31:45 -07:00
|
|
|
|
ds_put_cstr(s, " supported on Set-Field:");
|
2014-07-26 12:15:26 -07:00
|
|
|
|
BITMAP_FOR_EACH_1 (i, MFF_N_IDS, taf->set_fields.bm) {
|
2014-08-11 11:31:45 -07:00
|
|
|
|
ds_put_format(s, " %s", mf_from_id(i)->name);
|
2014-03-23 23:20:04 -07:00
|
|
|
|
}
|
2014-08-11 11:31:45 -07:00
|
|
|
|
ds_put_char(s, '\n');
|
2014-03-23 23:20:04 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
table_action_features_equal(const struct ofputil_table_action_features *a,
|
|
|
|
|
const struct ofputil_table_action_features *b)
|
|
|
|
|
{
|
2014-08-11 10:57:03 -07:00
|
|
|
|
return (a->ofpacts == b->ofpacts
|
2014-07-26 12:15:26 -07:00
|
|
|
|
&& bitmap_equal(a->set_fields.bm, b->set_fields.bm, MFF_N_IDS));
|
2014-03-23 23:20:04 -07:00
|
|
|
|
}
|
|
|
|
|
|
2014-08-11 11:31:45 -07:00
|
|
|
|
static bool
|
|
|
|
|
table_action_features_empty(const struct ofputil_table_action_features *taf)
|
|
|
|
|
{
|
|
|
|
|
return !taf->ofpacts && bitmap_is_all_zeros(taf->set_fields.bm, MFF_N_IDS);
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-23 23:20:04 -07:00
|
|
|
|
static void
|
|
|
|
|
print_table_instruction_features(
|
2015-07-06 22:15:40 -07:00
|
|
|
|
struct ds *s,
|
|
|
|
|
const struct ofputil_table_instruction_features *tif,
|
|
|
|
|
const struct ofputil_table_instruction_features *prev_tif)
|
2014-03-23 23:20:04 -07:00
|
|
|
|
{
|
|
|
|
|
int start, end;
|
|
|
|
|
|
2014-08-11 11:31:45 -07:00
|
|
|
|
if (!bitmap_is_all_zeros(tif->next, 255)) {
|
|
|
|
|
ds_put_cstr(s, " next tables: ");
|
|
|
|
|
for (start = bitmap_scan(tif->next, 1, 0, 255); start < 255;
|
|
|
|
|
start = bitmap_scan(tif->next, 1, end, 255)) {
|
|
|
|
|
end = bitmap_scan(tif->next, 0, start + 1, 255);
|
|
|
|
|
if (end == start + 1) {
|
|
|
|
|
ds_put_format(s, "%d,", start);
|
|
|
|
|
} else {
|
|
|
|
|
ds_put_format(s, "%d-%d,", start, end - 1);
|
|
|
|
|
}
|
2014-03-23 23:20:04 -07:00
|
|
|
|
}
|
2014-08-11 11:31:45 -07:00
|
|
|
|
ds_chomp(s, ',');
|
|
|
|
|
if (ds_last(s) == ' ') {
|
|
|
|
|
ds_put_cstr(s, "none");
|
|
|
|
|
}
|
|
|
|
|
ds_put_char(s, '\n');
|
2014-03-23 23:20:04 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (tif->instructions) {
|
2015-07-06 22:15:40 -07:00
|
|
|
|
if (prev_tif && tif->instructions == prev_tif->instructions) {
|
|
|
|
|
ds_put_cstr(s, " (same instructions)\n");
|
|
|
|
|
} else {
|
|
|
|
|
ds_put_cstr(s, " instructions: ");
|
|
|
|
|
int i;
|
2014-03-23 23:20:04 -07:00
|
|
|
|
|
2015-07-06 22:15:40 -07:00
|
|
|
|
for (i = 0; i < 32; i++) {
|
|
|
|
|
if (tif->instructions & (1u << i)) {
|
2017-05-26 19:59:47 -07:00
|
|
|
|
const char *name = ovs_instruction_name_from_type(i);
|
|
|
|
|
if (name) {
|
|
|
|
|
ds_put_cstr(s, name);
|
|
|
|
|
} else {
|
|
|
|
|
ds_put_format(s, "%d", i);
|
|
|
|
|
}
|
|
|
|
|
ds_put_char(s, ',');
|
2015-07-06 22:15:40 -07:00
|
|
|
|
}
|
2014-03-23 23:20:04 -07:00
|
|
|
|
}
|
2015-07-06 22:15:40 -07:00
|
|
|
|
ds_chomp(s, ',');
|
|
|
|
|
ds_put_char(s, '\n');
|
2014-03-23 23:20:04 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-06 22:15:40 -07:00
|
|
|
|
if (prev_tif
|
|
|
|
|
&& table_action_features_equal(&tif->write, &prev_tif->write)
|
|
|
|
|
&& table_action_features_equal(&tif->apply, &prev_tif->apply)
|
|
|
|
|
&& !bitmap_is_all_zeros(tif->write.set_fields.bm, MFF_N_IDS)) {
|
|
|
|
|
ds_put_cstr(s, " (same actions)\n");
|
|
|
|
|
} else if (!table_action_features_equal(&tif->write, &tif->apply)) {
|
2014-03-23 23:20:04 -07:00
|
|
|
|
ds_put_cstr(s, " Write-Actions features:\n");
|
|
|
|
|
print_table_action_features(s, &tif->write);
|
|
|
|
|
ds_put_cstr(s, " Apply-Actions features:\n");
|
|
|
|
|
print_table_action_features(s, &tif->apply);
|
2014-08-11 11:31:45 -07:00
|
|
|
|
} else if (tif->write.ofpacts
|
|
|
|
|
|| !bitmap_is_all_zeros(tif->write.set_fields.bm, MFF_N_IDS)) {
|
|
|
|
|
ds_put_cstr(s, " Write-Actions and Apply-Actions features:\n");
|
|
|
|
|
print_table_action_features(s, &tif->write);
|
2014-03-23 23:20:04 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
table_instruction_features_equal(
|
|
|
|
|
const struct ofputil_table_instruction_features *a,
|
|
|
|
|
const struct ofputil_table_instruction_features *b)
|
|
|
|
|
{
|
|
|
|
|
return (bitmap_equal(a->next, b->next, 255)
|
|
|
|
|
&& a->instructions == b->instructions
|
|
|
|
|
&& table_action_features_equal(&a->write, &b->write)
|
|
|
|
|
&& table_action_features_equal(&a->apply, &b->apply));
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-11 11:31:45 -07:00
|
|
|
|
static bool
|
|
|
|
|
table_instruction_features_empty(
|
|
|
|
|
const struct ofputil_table_instruction_features *tif)
|
2014-03-23 23:20:04 -07:00
|
|
|
|
{
|
2014-08-11 11:31:45 -07:00
|
|
|
|
return (bitmap_is_all_zeros(tif->next, 255)
|
|
|
|
|
&& !tif->instructions
|
|
|
|
|
&& table_action_features_empty(&tif->write)
|
|
|
|
|
&& table_action_features_empty(&tif->apply));
|
|
|
|
|
}
|
2014-03-23 23:20:04 -07:00
|
|
|
|
|
2015-07-06 22:15:40 -07:00
|
|
|
|
static bool
|
|
|
|
|
table_features_equal(const struct ofputil_table_features *a,
|
|
|
|
|
const struct ofputil_table_features *b)
|
|
|
|
|
{
|
|
|
|
|
return (a->metadata_match == b->metadata_match
|
|
|
|
|
&& a->metadata_write == b->metadata_write
|
|
|
|
|
&& a->miss_config == b->miss_config
|
|
|
|
|
&& a->supports_eviction == b->supports_eviction
|
|
|
|
|
&& a->supports_vacancy_events == b->supports_vacancy_events
|
|
|
|
|
&& a->max_entries == b->max_entries
|
|
|
|
|
&& table_instruction_features_equal(&a->nonmiss, &b->nonmiss)
|
|
|
|
|
&& table_instruction_features_equal(&a->miss, &b->miss)
|
|
|
|
|
&& bitmap_equal(a->match.bm, b->match.bm, MFF_N_IDS));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
table_features_empty(const struct ofputil_table_features *tf)
|
|
|
|
|
{
|
|
|
|
|
return (!tf->metadata_match
|
|
|
|
|
&& !tf->metadata_write
|
|
|
|
|
&& tf->miss_config == OFPUTIL_TABLE_MISS_DEFAULT
|
|
|
|
|
&& tf->supports_eviction < 0
|
|
|
|
|
&& tf->supports_vacancy_events < 0
|
|
|
|
|
&& !tf->max_entries
|
|
|
|
|
&& table_instruction_features_empty(&tf->nonmiss)
|
|
|
|
|
&& table_instruction_features_empty(&tf->miss)
|
|
|
|
|
&& bitmap_is_all_zeros(tf->match.bm, MFF_N_IDS));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
table_stats_equal(const struct ofputil_table_stats *a,
|
|
|
|
|
const struct ofputil_table_stats *b)
|
|
|
|
|
{
|
|
|
|
|
return (a->active_count == b->active_count
|
|
|
|
|
&& a->lookup_count == b->lookup_count
|
|
|
|
|
&& a->matched_count == b->matched_count);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2014-08-11 11:31:45 -07:00
|
|
|
|
ofp_print_table_features(struct ds *s,
|
|
|
|
|
const struct ofputil_table_features *features,
|
2015-07-06 22:15:40 -07:00
|
|
|
|
const struct ofputil_table_features *prev_features,
|
|
|
|
|
const struct ofputil_table_stats *stats,
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
const struct ofputil_table_stats *prev_stats,
|
|
|
|
|
const struct ofputil_table_map *table_map)
|
2014-08-11 11:31:45 -07:00
|
|
|
|
{
|
|
|
|
|
int i;
|
2014-03-23 23:20:04 -07:00
|
|
|
|
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
ds_put_format(s, " table ");
|
|
|
|
|
ofputil_format_table(features->table_id, table_map, s);
|
2014-08-11 11:31:45 -07:00
|
|
|
|
if (features->name[0]) {
|
|
|
|
|
ds_put_format(s, " (\"%s\")", features->name);
|
|
|
|
|
}
|
2015-07-06 22:15:40 -07:00
|
|
|
|
ds_put_char(s, ':');
|
|
|
|
|
|
|
|
|
|
bool same_stats = prev_stats && table_stats_equal(stats, prev_stats);
|
|
|
|
|
bool same_features = prev_features && table_features_equal(features,
|
|
|
|
|
prev_features);
|
2015-08-05 13:31:25 -07:00
|
|
|
|
if ((!stats || same_stats) && same_features) {
|
2015-07-06 22:15:40 -07:00
|
|
|
|
ds_put_cstr(s, " ditto");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
ds_put_char(s, '\n');
|
2014-08-11 11:31:45 -07:00
|
|
|
|
if (stats) {
|
|
|
|
|
ds_put_format(s, " active=%"PRIu32", ", stats->active_count);
|
|
|
|
|
ds_put_format(s, "lookup=%"PRIu64", ", stats->lookup_count);
|
|
|
|
|
ds_put_format(s, "matched=%"PRIu64"\n", stats->matched_count);
|
|
|
|
|
}
|
2015-07-06 22:15:40 -07:00
|
|
|
|
if (same_features) {
|
|
|
|
|
if (!table_features_empty(features)) {
|
|
|
|
|
ds_put_cstr(s, " (same features)\n");
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (features->metadata_match || features->metadata_write) {
|
2014-03-23 23:20:04 -07:00
|
|
|
|
ds_put_format(s, " metadata: match=%#"PRIx64" write=%#"PRIx64"\n",
|
2014-08-11 11:31:45 -07:00
|
|
|
|
ntohll(features->metadata_match),
|
|
|
|
|
ntohll(features->metadata_write));
|
|
|
|
|
}
|
2014-03-23 23:20:04 -07:00
|
|
|
|
|
2014-08-11 11:31:45 -07:00
|
|
|
|
if (features->miss_config != OFPUTIL_TABLE_MISS_DEFAULT) {
|
2015-07-02 20:33:08 -07:00
|
|
|
|
ds_put_format(s, " config=%s\n",
|
|
|
|
|
ofputil_table_miss_to_string(features->miss_config));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (features->supports_eviction >= 0) {
|
|
|
|
|
ds_put_format(s, " eviction: %ssupported\n",
|
|
|
|
|
features->supports_eviction ? "" : "not ");
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
if (features->supports_vacancy_events >= 0) {
|
|
|
|
|
ds_put_format(s, " vacancy events: %ssupported\n",
|
|
|
|
|
features->supports_vacancy_events ? "" : "not ");
|
|
|
|
|
|
2014-08-11 11:31:45 -07:00
|
|
|
|
}
|
2014-03-23 23:20:04 -07:00
|
|
|
|
|
2014-08-11 11:31:45 -07:00
|
|
|
|
if (features->max_entries) {
|
|
|
|
|
ds_put_format(s, " max_entries=%"PRIu32"\n", features->max_entries);
|
|
|
|
|
}
|
2014-03-23 23:20:04 -07:00
|
|
|
|
|
2015-07-06 22:15:40 -07:00
|
|
|
|
const struct ofputil_table_instruction_features *prev_nonmiss
|
|
|
|
|
= prev_features ? &prev_features->nonmiss : NULL;
|
|
|
|
|
const struct ofputil_table_instruction_features *prev_miss
|
|
|
|
|
= prev_features ? &prev_features->miss : NULL;
|
|
|
|
|
if (prev_features
|
|
|
|
|
&& table_instruction_features_equal(&features->nonmiss, prev_nonmiss)
|
|
|
|
|
&& table_instruction_features_equal(&features->miss, prev_miss)) {
|
|
|
|
|
if (!table_instruction_features_empty(&features->nonmiss)) {
|
|
|
|
|
ds_put_cstr(s, " (same instructions)\n");
|
|
|
|
|
}
|
|
|
|
|
} else if (!table_instruction_features_equal(&features->nonmiss,
|
|
|
|
|
&features->miss)) {
|
2014-08-11 11:31:45 -07:00
|
|
|
|
ds_put_cstr(s, " instructions (other than table miss):\n");
|
2015-07-06 22:15:40 -07:00
|
|
|
|
print_table_instruction_features(s, &features->nonmiss, prev_nonmiss);
|
2014-08-11 11:31:45 -07:00
|
|
|
|
ds_put_cstr(s, " instructions (table miss):\n");
|
2015-07-06 22:15:40 -07:00
|
|
|
|
print_table_instruction_features(s, &features->miss, prev_miss);
|
2014-08-11 11:31:45 -07:00
|
|
|
|
} else if (!table_instruction_features_empty(&features->nonmiss)) {
|
|
|
|
|
ds_put_cstr(s, " instructions (table miss and others):\n");
|
2015-07-06 22:15:40 -07:00
|
|
|
|
print_table_instruction_features(s, &features->nonmiss, prev_nonmiss);
|
2014-08-11 11:31:45 -07:00
|
|
|
|
}
|
2014-03-23 23:20:04 -07:00
|
|
|
|
|
2015-07-06 22:15:40 -07:00
|
|
|
|
if (!bitmap_is_all_zeros(features->match.bm, MFF_N_IDS)) {
|
|
|
|
|
if (prev_features
|
|
|
|
|
&& bitmap_equal(features->match.bm, prev_features->match.bm,
|
|
|
|
|
MFF_N_IDS)) {
|
|
|
|
|
ds_put_cstr(s, " (same matching)\n");
|
|
|
|
|
} else {
|
|
|
|
|
ds_put_cstr(s, " matching:\n");
|
|
|
|
|
BITMAP_FOR_EACH_1 (i, MFF_N_IDS, features->match.bm) {
|
|
|
|
|
const struct mf_field *f = mf_from_id(i);
|
|
|
|
|
bool mask = bitmap_is_set(features->mask.bm, i);
|
|
|
|
|
bool wildcard = bitmap_is_set(features->wildcard.bm, i);
|
|
|
|
|
|
|
|
|
|
ds_put_format(s, " %s: %s\n",
|
|
|
|
|
f->name,
|
|
|
|
|
(mask ? "arbitrary mask"
|
|
|
|
|
: wildcard ? "exact match or wildcard"
|
|
|
|
|
: "must exact match"));
|
|
|
|
|
}
|
2014-03-23 23:20:04 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
ofp_print_table_features_reply(struct ds *s, const struct ofp_header *oh,
|
|
|
|
|
const struct ofputil_table_map *table_map)
|
2014-08-11 11:31:45 -07:00
|
|
|
|
{
|
2016-02-18 15:13:09 -08:00
|
|
|
|
struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
|
2014-08-11 11:31:45 -07:00
|
|
|
|
|
2015-07-06 22:15:40 -07:00
|
|
|
|
struct ofputil_table_features prev;
|
|
|
|
|
for (int i = 0; ; i++) {
|
2014-08-11 11:31:45 -07:00
|
|
|
|
struct ofputil_table_features tf;
|
|
|
|
|
int retval;
|
|
|
|
|
|
|
|
|
|
retval = ofputil_decode_table_features(&b, &tf, true);
|
|
|
|
|
if (retval) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return retval != EOF ? retval : 0;
|
2014-08-11 11:31:45 -07:00
|
|
|
|
}
|
2015-07-06 22:15:40 -07:00
|
|
|
|
|
|
|
|
|
ds_put_char(s, '\n');
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
ofp_print_table_features(s, &tf, i ? &prev : NULL, NULL, NULL,
|
|
|
|
|
table_map);
|
2015-07-06 22:15:40 -07:00
|
|
|
|
prev = tf;
|
2014-08-11 11:31:45 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
ofp_print_table_desc_reply(struct ds *s, const struct ofp_header *oh,
|
|
|
|
|
const struct ofputil_table_map *table_map)
|
2015-07-02 20:35:44 -07:00
|
|
|
|
{
|
2016-02-18 15:13:09 -08:00
|
|
|
|
struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
|
2015-07-02 20:35:44 -07:00
|
|
|
|
for (;;) {
|
|
|
|
|
struct ofputil_table_desc td;
|
|
|
|
|
int retval;
|
|
|
|
|
|
|
|
|
|
retval = ofputil_decode_table_desc(&b, &td, oh->version);
|
|
|
|
|
if (retval) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return retval != EOF ? retval : 0;
|
2015-07-02 20:35:44 -07:00
|
|
|
|
}
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
ofp_print_table_desc(s, &td, table_map);
|
2015-07-02 20:35:44 -07:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-02 09:54:27 +03:00
|
|
|
|
static const char *
|
|
|
|
|
bundle_flags_to_name(uint32_t bit)
|
|
|
|
|
{
|
|
|
|
|
switch (bit) {
|
|
|
|
|
case OFPBF_ATOMIC:
|
|
|
|
|
return "atomic";
|
|
|
|
|
case OFPBF_ORDERED:
|
|
|
|
|
return "ordered";
|
|
|
|
|
default:
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2014-05-02 09:54:27 +03:00
|
|
|
|
ofp_print_bundle_ctrl(struct ds *s, const struct ofp_header *oh)
|
|
|
|
|
{
|
|
|
|
|
int error;
|
|
|
|
|
struct ofputil_bundle_ctrl_msg bctrl;
|
|
|
|
|
|
|
|
|
|
error = ofputil_decode_bundle_ctrl(oh, &bctrl);
|
|
|
|
|
if (error) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return error;
|
2014-05-02 09:54:27 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ds_put_char(s, '\n');
|
|
|
|
|
|
|
|
|
|
ds_put_format(s, " bundle_id=%#"PRIx32" type=", bctrl.bundle_id);
|
|
|
|
|
switch (bctrl.type) {
|
|
|
|
|
case OFPBCT_OPEN_REQUEST:
|
|
|
|
|
ds_put_cstr(s, "OPEN_REQUEST");
|
|
|
|
|
break;
|
|
|
|
|
case OFPBCT_OPEN_REPLY:
|
|
|
|
|
ds_put_cstr(s, "OPEN_REPLY");
|
|
|
|
|
break;
|
|
|
|
|
case OFPBCT_CLOSE_REQUEST:
|
|
|
|
|
ds_put_cstr(s, "CLOSE_REQUEST");
|
|
|
|
|
break;
|
|
|
|
|
case OFPBCT_CLOSE_REPLY:
|
|
|
|
|
ds_put_cstr(s, "CLOSE_REPLY");
|
|
|
|
|
break;
|
|
|
|
|
case OFPBCT_COMMIT_REQUEST:
|
|
|
|
|
ds_put_cstr(s, "COMMIT_REQUEST");
|
|
|
|
|
break;
|
|
|
|
|
case OFPBCT_COMMIT_REPLY:
|
|
|
|
|
ds_put_cstr(s, "COMMIT_REPLY");
|
|
|
|
|
break;
|
|
|
|
|
case OFPBCT_DISCARD_REQUEST:
|
|
|
|
|
ds_put_cstr(s, "DISCARD_REQUEST");
|
|
|
|
|
break;
|
|
|
|
|
case OFPBCT_DISCARD_REPLY:
|
|
|
|
|
ds_put_cstr(s, "DISCARD_REPLY");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ds_put_cstr(s, " flags=");
|
|
|
|
|
ofp_print_bit_names(s, bctrl.flags, bundle_flags_to_name, ' ');
|
2018-01-04 22:40:01 -08:00
|
|
|
|
|
|
|
|
|
return 0;
|
2014-05-02 09:54:27 +03:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ofp_print_bundle_add(struct ds *s, const struct ofp_header *oh,
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
const struct ofputil_port_map *port_map,
|
|
|
|
|
const struct ofputil_table_map *table_map,
|
|
|
|
|
int verbosity)
|
2014-05-02 09:54:27 +03:00
|
|
|
|
{
|
|
|
|
|
int error;
|
|
|
|
|
struct ofputil_bundle_add_msg badd;
|
|
|
|
|
|
2015-06-01 18:07:39 -07:00
|
|
|
|
error = ofputil_decode_bundle_add(oh, &badd, NULL);
|
2014-05-02 09:54:27 +03:00
|
|
|
|
if (error) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return error;
|
2014-05-02 09:54:27 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ds_put_char(s, '\n');
|
|
|
|
|
ds_put_format(s, " bundle_id=%#"PRIx32, badd.bundle_id);
|
|
|
|
|
ds_put_cstr(s, " flags=");
|
|
|
|
|
ofp_print_bit_names(s, badd.flags, bundle_flags_to_name, ' ');
|
|
|
|
|
|
|
|
|
|
ds_put_char(s, '\n');
|
2017-05-31 16:06:12 -07:00
|
|
|
|
char *msg = ofp_to_string(badd.msg, ntohs(badd.msg->length), port_map,
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
table_map, verbosity);
|
2015-12-24 10:28:40 -08:00
|
|
|
|
ds_put_and_free_cstr(s, msg);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
|
|
|
|
|
return 0;
|
2014-05-02 09:54:27 +03:00
|
|
|
|
}
|
|
|
|
|
|
openflow: Table maintenance commands for Geneve options.
In order to work with Geneve options, we need to maintain a mapping
table between an option (defined by <class, type, length>) and
an NXM field that can be operated on for the purposes of matches,
actions, etc. This mapping must be explicitly specified by the
user.
Conceptually, this table could be communicated using either OpenFlow
or OVSDB. Using OVSDB requires less code and definition of extensions
than OpenFlow but introduces the possibility that mapping table
updates and flow modifications are desynchronized from each other.
This is dangerous because the mapping table signifcantly impacts the
way that flows using Geneve options are installed and processed by
OVS. Therefore, the mapping table is maintained using OpenFlow commands
instead, which opens the possibility of using synchronization between
table changes and flow modifications through barriers, bundles, etc.
There are two primary groups of OpenFlow messages that are introduced
as Nicira extensions: modification commands (add, delete, clear mappings)
and table status request/reply to dump the current table along with switch
information.
Note that mappings should not be changed while they are in active use by
a flow. The result of doing so is undefined.
This only adds the OpenFlow infrastructure but doesn't actually
do anything with the information yet after the messages have been
decoded.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-06-02 15:11:00 -07:00
|
|
|
|
static void
|
2015-12-16 02:47:50 +08:00
|
|
|
|
print_tlv_table(struct ds *s, struct ovs_list *mappings)
|
openflow: Table maintenance commands for Geneve options.
In order to work with Geneve options, we need to maintain a mapping
table between an option (defined by <class, type, length>) and
an NXM field that can be operated on for the purposes of matches,
actions, etc. This mapping must be explicitly specified by the
user.
Conceptually, this table could be communicated using either OpenFlow
or OVSDB. Using OVSDB requires less code and definition of extensions
than OpenFlow but introduces the possibility that mapping table
updates and flow modifications are desynchronized from each other.
This is dangerous because the mapping table signifcantly impacts the
way that flows using Geneve options are installed and processed by
OVS. Therefore, the mapping table is maintained using OpenFlow commands
instead, which opens the possibility of using synchronization between
table changes and flow modifications through barriers, bundles, etc.
There are two primary groups of OpenFlow messages that are introduced
as Nicira extensions: modification commands (add, delete, clear mappings)
and table status request/reply to dump the current table along with switch
information.
Note that mappings should not be changed while they are in active use by
a flow. The result of doing so is undefined.
This only adds the OpenFlow infrastructure but doesn't actually
do anything with the information yet after the messages have been
decoded.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-06-02 15:11:00 -07:00
|
|
|
|
{
|
2015-12-16 02:47:50 +08:00
|
|
|
|
struct ofputil_tlv_map *map;
|
openflow: Table maintenance commands for Geneve options.
In order to work with Geneve options, we need to maintain a mapping
table between an option (defined by <class, type, length>) and
an NXM field that can be operated on for the purposes of matches,
actions, etc. This mapping must be explicitly specified by the
user.
Conceptually, this table could be communicated using either OpenFlow
or OVSDB. Using OVSDB requires less code and definition of extensions
than OpenFlow but introduces the possibility that mapping table
updates and flow modifications are desynchronized from each other.
This is dangerous because the mapping table signifcantly impacts the
way that flows using Geneve options are installed and processed by
OVS. Therefore, the mapping table is maintained using OpenFlow commands
instead, which opens the possibility of using synchronization between
table changes and flow modifications through barriers, bundles, etc.
There are two primary groups of OpenFlow messages that are introduced
as Nicira extensions: modification commands (add, delete, clear mappings)
and table status request/reply to dump the current table along with switch
information.
Note that mappings should not be changed while they are in active use by
a flow. The result of doing so is undefined.
This only adds the OpenFlow infrastructure but doesn't actually
do anything with the information yet after the messages have been
decoded.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-06-02 15:11:00 -07:00
|
|
|
|
|
|
|
|
|
ds_put_cstr(s, " mapping table:\n");
|
|
|
|
|
ds_put_cstr(s, " class\ttype\tlength\tmatch field\n");
|
|
|
|
|
ds_put_cstr(s, " -----\t----\t------\t-----------");
|
|
|
|
|
|
|
|
|
|
LIST_FOR_EACH (map, list_node, mappings) {
|
|
|
|
|
ds_put_char(s, '\n');
|
|
|
|
|
ds_put_format(s, " 0x%"PRIx16"\t0x%"PRIx8"\t%"PRIu8"\ttun_metadata%"PRIu16,
|
|
|
|
|
map->option_class, map->option_type, map->option_len,
|
|
|
|
|
map->index);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2015-12-16 02:47:50 +08:00
|
|
|
|
ofp_print_tlv_table_mod(struct ds *s, const struct ofp_header *oh)
|
openflow: Table maintenance commands for Geneve options.
In order to work with Geneve options, we need to maintain a mapping
table between an option (defined by <class, type, length>) and
an NXM field that can be operated on for the purposes of matches,
actions, etc. This mapping must be explicitly specified by the
user.
Conceptually, this table could be communicated using either OpenFlow
or OVSDB. Using OVSDB requires less code and definition of extensions
than OpenFlow but introduces the possibility that mapping table
updates and flow modifications are desynchronized from each other.
This is dangerous because the mapping table signifcantly impacts the
way that flows using Geneve options are installed and processed by
OVS. Therefore, the mapping table is maintained using OpenFlow commands
instead, which opens the possibility of using synchronization between
table changes and flow modifications through barriers, bundles, etc.
There are two primary groups of OpenFlow messages that are introduced
as Nicira extensions: modification commands (add, delete, clear mappings)
and table status request/reply to dump the current table along with switch
information.
Note that mappings should not be changed while they are in active use by
a flow. The result of doing so is undefined.
This only adds the OpenFlow infrastructure but doesn't actually
do anything with the information yet after the messages have been
decoded.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-06-02 15:11:00 -07:00
|
|
|
|
{
|
|
|
|
|
int error;
|
2015-12-16 02:47:50 +08:00
|
|
|
|
struct ofputil_tlv_table_mod ttm;
|
openflow: Table maintenance commands for Geneve options.
In order to work with Geneve options, we need to maintain a mapping
table between an option (defined by <class, type, length>) and
an NXM field that can be operated on for the purposes of matches,
actions, etc. This mapping must be explicitly specified by the
user.
Conceptually, this table could be communicated using either OpenFlow
or OVSDB. Using OVSDB requires less code and definition of extensions
than OpenFlow but introduces the possibility that mapping table
updates and flow modifications are desynchronized from each other.
This is dangerous because the mapping table signifcantly impacts the
way that flows using Geneve options are installed and processed by
OVS. Therefore, the mapping table is maintained using OpenFlow commands
instead, which opens the possibility of using synchronization between
table changes and flow modifications through barriers, bundles, etc.
There are two primary groups of OpenFlow messages that are introduced
as Nicira extensions: modification commands (add, delete, clear mappings)
and table status request/reply to dump the current table along with switch
information.
Note that mappings should not be changed while they are in active use by
a flow. The result of doing so is undefined.
This only adds the OpenFlow infrastructure but doesn't actually
do anything with the information yet after the messages have been
decoded.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-06-02 15:11:00 -07:00
|
|
|
|
|
2015-12-16 02:47:50 +08:00
|
|
|
|
error = ofputil_decode_tlv_table_mod(oh, &ttm);
|
openflow: Table maintenance commands for Geneve options.
In order to work with Geneve options, we need to maintain a mapping
table between an option (defined by <class, type, length>) and
an NXM field that can be operated on for the purposes of matches,
actions, etc. This mapping must be explicitly specified by the
user.
Conceptually, this table could be communicated using either OpenFlow
or OVSDB. Using OVSDB requires less code and definition of extensions
than OpenFlow but introduces the possibility that mapping table
updates and flow modifications are desynchronized from each other.
This is dangerous because the mapping table signifcantly impacts the
way that flows using Geneve options are installed and processed by
OVS. Therefore, the mapping table is maintained using OpenFlow commands
instead, which opens the possibility of using synchronization between
table changes and flow modifications through barriers, bundles, etc.
There are two primary groups of OpenFlow messages that are introduced
as Nicira extensions: modification commands (add, delete, clear mappings)
and table status request/reply to dump the current table along with switch
information.
Note that mappings should not be changed while they are in active use by
a flow. The result of doing so is undefined.
This only adds the OpenFlow infrastructure but doesn't actually
do anything with the information yet after the messages have been
decoded.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-06-02 15:11:00 -07:00
|
|
|
|
if (error) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return error;
|
openflow: Table maintenance commands for Geneve options.
In order to work with Geneve options, we need to maintain a mapping
table between an option (defined by <class, type, length>) and
an NXM field that can be operated on for the purposes of matches,
actions, etc. This mapping must be explicitly specified by the
user.
Conceptually, this table could be communicated using either OpenFlow
or OVSDB. Using OVSDB requires less code and definition of extensions
than OpenFlow but introduces the possibility that mapping table
updates and flow modifications are desynchronized from each other.
This is dangerous because the mapping table signifcantly impacts the
way that flows using Geneve options are installed and processed by
OVS. Therefore, the mapping table is maintained using OpenFlow commands
instead, which opens the possibility of using synchronization between
table changes and flow modifications through barriers, bundles, etc.
There are two primary groups of OpenFlow messages that are introduced
as Nicira extensions: modification commands (add, delete, clear mappings)
and table status request/reply to dump the current table along with switch
information.
Note that mappings should not be changed while they are in active use by
a flow. The result of doing so is undefined.
This only adds the OpenFlow infrastructure but doesn't actually
do anything with the information yet after the messages have been
decoded.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-06-02 15:11:00 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ds_put_cstr(s, "\n ");
|
|
|
|
|
|
2015-12-16 02:47:50 +08:00
|
|
|
|
switch (ttm.command) {
|
|
|
|
|
case NXTTMC_ADD:
|
openflow: Table maintenance commands for Geneve options.
In order to work with Geneve options, we need to maintain a mapping
table between an option (defined by <class, type, length>) and
an NXM field that can be operated on for the purposes of matches,
actions, etc. This mapping must be explicitly specified by the
user.
Conceptually, this table could be communicated using either OpenFlow
or OVSDB. Using OVSDB requires less code and definition of extensions
than OpenFlow but introduces the possibility that mapping table
updates and flow modifications are desynchronized from each other.
This is dangerous because the mapping table signifcantly impacts the
way that flows using Geneve options are installed and processed by
OVS. Therefore, the mapping table is maintained using OpenFlow commands
instead, which opens the possibility of using synchronization between
table changes and flow modifications through barriers, bundles, etc.
There are two primary groups of OpenFlow messages that are introduced
as Nicira extensions: modification commands (add, delete, clear mappings)
and table status request/reply to dump the current table along with switch
information.
Note that mappings should not be changed while they are in active use by
a flow. The result of doing so is undefined.
This only adds the OpenFlow infrastructure but doesn't actually
do anything with the information yet after the messages have been
decoded.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-06-02 15:11:00 -07:00
|
|
|
|
ds_put_cstr(s, "ADD");
|
|
|
|
|
break;
|
2015-12-16 02:47:50 +08:00
|
|
|
|
case NXTTMC_DELETE:
|
openflow: Table maintenance commands for Geneve options.
In order to work with Geneve options, we need to maintain a mapping
table between an option (defined by <class, type, length>) and
an NXM field that can be operated on for the purposes of matches,
actions, etc. This mapping must be explicitly specified by the
user.
Conceptually, this table could be communicated using either OpenFlow
or OVSDB. Using OVSDB requires less code and definition of extensions
than OpenFlow but introduces the possibility that mapping table
updates and flow modifications are desynchronized from each other.
This is dangerous because the mapping table signifcantly impacts the
way that flows using Geneve options are installed and processed by
OVS. Therefore, the mapping table is maintained using OpenFlow commands
instead, which opens the possibility of using synchronization between
table changes and flow modifications through barriers, bundles, etc.
There are two primary groups of OpenFlow messages that are introduced
as Nicira extensions: modification commands (add, delete, clear mappings)
and table status request/reply to dump the current table along with switch
information.
Note that mappings should not be changed while they are in active use by
a flow. The result of doing so is undefined.
This only adds the OpenFlow infrastructure but doesn't actually
do anything with the information yet after the messages have been
decoded.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-06-02 15:11:00 -07:00
|
|
|
|
ds_put_cstr(s, "DEL");
|
|
|
|
|
break;
|
2015-12-16 02:47:50 +08:00
|
|
|
|
case NXTTMC_CLEAR:
|
openflow: Table maintenance commands for Geneve options.
In order to work with Geneve options, we need to maintain a mapping
table between an option (defined by <class, type, length>) and
an NXM field that can be operated on for the purposes of matches,
actions, etc. This mapping must be explicitly specified by the
user.
Conceptually, this table could be communicated using either OpenFlow
or OVSDB. Using OVSDB requires less code and definition of extensions
than OpenFlow but introduces the possibility that mapping table
updates and flow modifications are desynchronized from each other.
This is dangerous because the mapping table signifcantly impacts the
way that flows using Geneve options are installed and processed by
OVS. Therefore, the mapping table is maintained using OpenFlow commands
instead, which opens the possibility of using synchronization between
table changes and flow modifications through barriers, bundles, etc.
There are two primary groups of OpenFlow messages that are introduced
as Nicira extensions: modification commands (add, delete, clear mappings)
and table status request/reply to dump the current table along with switch
information.
Note that mappings should not be changed while they are in active use by
a flow. The result of doing so is undefined.
This only adds the OpenFlow infrastructure but doesn't actually
do anything with the information yet after the messages have been
decoded.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-06-02 15:11:00 -07:00
|
|
|
|
ds_put_cstr(s, "CLEAR");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-16 02:47:50 +08:00
|
|
|
|
if (ttm.command != NXTTMC_CLEAR) {
|
|
|
|
|
print_tlv_table(s, &ttm.mappings);
|
openflow: Table maintenance commands for Geneve options.
In order to work with Geneve options, we need to maintain a mapping
table between an option (defined by <class, type, length>) and
an NXM field that can be operated on for the purposes of matches,
actions, etc. This mapping must be explicitly specified by the
user.
Conceptually, this table could be communicated using either OpenFlow
or OVSDB. Using OVSDB requires less code and definition of extensions
than OpenFlow but introduces the possibility that mapping table
updates and flow modifications are desynchronized from each other.
This is dangerous because the mapping table signifcantly impacts the
way that flows using Geneve options are installed and processed by
OVS. Therefore, the mapping table is maintained using OpenFlow commands
instead, which opens the possibility of using synchronization between
table changes and flow modifications through barriers, bundles, etc.
There are two primary groups of OpenFlow messages that are introduced
as Nicira extensions: modification commands (add, delete, clear mappings)
and table status request/reply to dump the current table along with switch
information.
Note that mappings should not be changed while they are in active use by
a flow. The result of doing so is undefined.
This only adds the OpenFlow infrastructure but doesn't actually
do anything with the information yet after the messages have been
decoded.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-06-02 15:11:00 -07:00
|
|
|
|
}
|
|
|
|
|
|
2015-12-16 02:47:50 +08:00
|
|
|
|
ofputil_uninit_tlv_table(&ttm.mappings);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
|
|
|
|
|
return 0;
|
openflow: Table maintenance commands for Geneve options.
In order to work with Geneve options, we need to maintain a mapping
table between an option (defined by <class, type, length>) and
an NXM field that can be operated on for the purposes of matches,
actions, etc. This mapping must be explicitly specified by the
user.
Conceptually, this table could be communicated using either OpenFlow
or OVSDB. Using OVSDB requires less code and definition of extensions
than OpenFlow but introduces the possibility that mapping table
updates and flow modifications are desynchronized from each other.
This is dangerous because the mapping table signifcantly impacts the
way that flows using Geneve options are installed and processed by
OVS. Therefore, the mapping table is maintained using OpenFlow commands
instead, which opens the possibility of using synchronization between
table changes and flow modifications through barriers, bundles, etc.
There are two primary groups of OpenFlow messages that are introduced
as Nicira extensions: modification commands (add, delete, clear mappings)
and table status request/reply to dump the current table along with switch
information.
Note that mappings should not be changed while they are in active use by
a flow. The result of doing so is undefined.
This only adds the OpenFlow infrastructure but doesn't actually
do anything with the information yet after the messages have been
decoded.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-06-02 15:11:00 -07:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2015-12-16 02:47:50 +08:00
|
|
|
|
ofp_print_tlv_table_reply(struct ds *s, const struct ofp_header *oh)
|
openflow: Table maintenance commands for Geneve options.
In order to work with Geneve options, we need to maintain a mapping
table between an option (defined by <class, type, length>) and
an NXM field that can be operated on for the purposes of matches,
actions, etc. This mapping must be explicitly specified by the
user.
Conceptually, this table could be communicated using either OpenFlow
or OVSDB. Using OVSDB requires less code and definition of extensions
than OpenFlow but introduces the possibility that mapping table
updates and flow modifications are desynchronized from each other.
This is dangerous because the mapping table signifcantly impacts the
way that flows using Geneve options are installed and processed by
OVS. Therefore, the mapping table is maintained using OpenFlow commands
instead, which opens the possibility of using synchronization between
table changes and flow modifications through barriers, bundles, etc.
There are two primary groups of OpenFlow messages that are introduced
as Nicira extensions: modification commands (add, delete, clear mappings)
and table status request/reply to dump the current table along with switch
information.
Note that mappings should not be changed while they are in active use by
a flow. The result of doing so is undefined.
This only adds the OpenFlow infrastructure but doesn't actually
do anything with the information yet after the messages have been
decoded.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-06-02 15:11:00 -07:00
|
|
|
|
{
|
|
|
|
|
int error;
|
2015-12-16 02:47:50 +08:00
|
|
|
|
struct ofputil_tlv_table_reply ttr;
|
|
|
|
|
struct ofputil_tlv_map *map;
|
openflow: Table maintenance commands for Geneve options.
In order to work with Geneve options, we need to maintain a mapping
table between an option (defined by <class, type, length>) and
an NXM field that can be operated on for the purposes of matches,
actions, etc. This mapping must be explicitly specified by the
user.
Conceptually, this table could be communicated using either OpenFlow
or OVSDB. Using OVSDB requires less code and definition of extensions
than OpenFlow but introduces the possibility that mapping table
updates and flow modifications are desynchronized from each other.
This is dangerous because the mapping table signifcantly impacts the
way that flows using Geneve options are installed and processed by
OVS. Therefore, the mapping table is maintained using OpenFlow commands
instead, which opens the possibility of using synchronization between
table changes and flow modifications through barriers, bundles, etc.
There are two primary groups of OpenFlow messages that are introduced
as Nicira extensions: modification commands (add, delete, clear mappings)
and table status request/reply to dump the current table along with switch
information.
Note that mappings should not be changed while they are in active use by
a flow. The result of doing so is undefined.
This only adds the OpenFlow infrastructure but doesn't actually
do anything with the information yet after the messages have been
decoded.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-06-02 15:11:00 -07:00
|
|
|
|
int allocated_space = 0;
|
|
|
|
|
|
2015-12-16 02:47:50 +08:00
|
|
|
|
error = ofputil_decode_tlv_table_reply(oh, &ttr);
|
openflow: Table maintenance commands for Geneve options.
In order to work with Geneve options, we need to maintain a mapping
table between an option (defined by <class, type, length>) and
an NXM field that can be operated on for the purposes of matches,
actions, etc. This mapping must be explicitly specified by the
user.
Conceptually, this table could be communicated using either OpenFlow
or OVSDB. Using OVSDB requires less code and definition of extensions
than OpenFlow but introduces the possibility that mapping table
updates and flow modifications are desynchronized from each other.
This is dangerous because the mapping table signifcantly impacts the
way that flows using Geneve options are installed and processed by
OVS. Therefore, the mapping table is maintained using OpenFlow commands
instead, which opens the possibility of using synchronization between
table changes and flow modifications through barriers, bundles, etc.
There are two primary groups of OpenFlow messages that are introduced
as Nicira extensions: modification commands (add, delete, clear mappings)
and table status request/reply to dump the current table along with switch
information.
Note that mappings should not be changed while they are in active use by
a flow. The result of doing so is undefined.
This only adds the OpenFlow infrastructure but doesn't actually
do anything with the information yet after the messages have been
decoded.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-06-02 15:11:00 -07:00
|
|
|
|
if (error) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return error;
|
openflow: Table maintenance commands for Geneve options.
In order to work with Geneve options, we need to maintain a mapping
table between an option (defined by <class, type, length>) and
an NXM field that can be operated on for the purposes of matches,
actions, etc. This mapping must be explicitly specified by the
user.
Conceptually, this table could be communicated using either OpenFlow
or OVSDB. Using OVSDB requires less code and definition of extensions
than OpenFlow but introduces the possibility that mapping table
updates and flow modifications are desynchronized from each other.
This is dangerous because the mapping table signifcantly impacts the
way that flows using Geneve options are installed and processed by
OVS. Therefore, the mapping table is maintained using OpenFlow commands
instead, which opens the possibility of using synchronization between
table changes and flow modifications through barriers, bundles, etc.
There are two primary groups of OpenFlow messages that are introduced
as Nicira extensions: modification commands (add, delete, clear mappings)
and table status request/reply to dump the current table along with switch
information.
Note that mappings should not be changed while they are in active use by
a flow. The result of doing so is undefined.
This only adds the OpenFlow infrastructure but doesn't actually
do anything with the information yet after the messages have been
decoded.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-06-02 15:11:00 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ds_put_char(s, '\n');
|
|
|
|
|
|
2015-12-16 02:47:50 +08:00
|
|
|
|
LIST_FOR_EACH (map, list_node, &ttr.mappings) {
|
openflow: Table maintenance commands for Geneve options.
In order to work with Geneve options, we need to maintain a mapping
table between an option (defined by <class, type, length>) and
an NXM field that can be operated on for the purposes of matches,
actions, etc. This mapping must be explicitly specified by the
user.
Conceptually, this table could be communicated using either OpenFlow
or OVSDB. Using OVSDB requires less code and definition of extensions
than OpenFlow but introduces the possibility that mapping table
updates and flow modifications are desynchronized from each other.
This is dangerous because the mapping table signifcantly impacts the
way that flows using Geneve options are installed and processed by
OVS. Therefore, the mapping table is maintained using OpenFlow commands
instead, which opens the possibility of using synchronization between
table changes and flow modifications through barriers, bundles, etc.
There are two primary groups of OpenFlow messages that are introduced
as Nicira extensions: modification commands (add, delete, clear mappings)
and table status request/reply to dump the current table along with switch
information.
Note that mappings should not be changed while they are in active use by
a flow. The result of doing so is undefined.
This only adds the OpenFlow infrastructure but doesn't actually
do anything with the information yet after the messages have been
decoded.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-06-02 15:11:00 -07:00
|
|
|
|
allocated_space += map->option_len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ds_put_format(s, " max option space=%"PRIu32" max fields=%"PRIu16"\n",
|
2015-12-16 02:47:50 +08:00
|
|
|
|
ttr.max_option_space, ttr.max_fields);
|
openflow: Table maintenance commands for Geneve options.
In order to work with Geneve options, we need to maintain a mapping
table between an option (defined by <class, type, length>) and
an NXM field that can be operated on for the purposes of matches,
actions, etc. This mapping must be explicitly specified by the
user.
Conceptually, this table could be communicated using either OpenFlow
or OVSDB. Using OVSDB requires less code and definition of extensions
than OpenFlow but introduces the possibility that mapping table
updates and flow modifications are desynchronized from each other.
This is dangerous because the mapping table signifcantly impacts the
way that flows using Geneve options are installed and processed by
OVS. Therefore, the mapping table is maintained using OpenFlow commands
instead, which opens the possibility of using synchronization between
table changes and flow modifications through barriers, bundles, etc.
There are two primary groups of OpenFlow messages that are introduced
as Nicira extensions: modification commands (add, delete, clear mappings)
and table status request/reply to dump the current table along with switch
information.
Note that mappings should not be changed while they are in active use by
a flow. The result of doing so is undefined.
This only adds the OpenFlow infrastructure but doesn't actually
do anything with the information yet after the messages have been
decoded.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-06-02 15:11:00 -07:00
|
|
|
|
ds_put_format(s, " allocated option space=%d\n", allocated_space);
|
|
|
|
|
ds_put_char(s, '\n');
|
2015-12-16 02:47:50 +08:00
|
|
|
|
print_tlv_table(s, &ttr.mappings);
|
openflow: Table maintenance commands for Geneve options.
In order to work with Geneve options, we need to maintain a mapping
table between an option (defined by <class, type, length>) and
an NXM field that can be operated on for the purposes of matches,
actions, etc. This mapping must be explicitly specified by the
user.
Conceptually, this table could be communicated using either OpenFlow
or OVSDB. Using OVSDB requires less code and definition of extensions
than OpenFlow but introduces the possibility that mapping table
updates and flow modifications are desynchronized from each other.
This is dangerous because the mapping table signifcantly impacts the
way that flows using Geneve options are installed and processed by
OVS. Therefore, the mapping table is maintained using OpenFlow commands
instead, which opens the possibility of using synchronization between
table changes and flow modifications through barriers, bundles, etc.
There are two primary groups of OpenFlow messages that are introduced
as Nicira extensions: modification commands (add, delete, clear mappings)
and table status request/reply to dump the current table along with switch
information.
Note that mappings should not be changed while they are in active use by
a flow. The result of doing so is undefined.
This only adds the OpenFlow infrastructure but doesn't actually
do anything with the information yet after the messages have been
decoded.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-06-02 15:11:00 -07:00
|
|
|
|
|
2015-12-16 02:47:50 +08:00
|
|
|
|
ofputil_uninit_tlv_table(&ttr.mappings);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
|
|
|
|
|
return 0;
|
openflow: Table maintenance commands for Geneve options.
In order to work with Geneve options, we need to maintain a mapping
table between an option (defined by <class, type, length>) and
an NXM field that can be operated on for the purposes of matches,
actions, etc. This mapping must be explicitly specified by the
user.
Conceptually, this table could be communicated using either OpenFlow
or OVSDB. Using OVSDB requires less code and definition of extensions
than OpenFlow but introduces the possibility that mapping table
updates and flow modifications are desynchronized from each other.
This is dangerous because the mapping table signifcantly impacts the
way that flows using Geneve options are installed and processed by
OVS. Therefore, the mapping table is maintained using OpenFlow commands
instead, which opens the possibility of using synchronization between
table changes and flow modifications through barriers, bundles, etc.
There are two primary groups of OpenFlow messages that are introduced
as Nicira extensions: modification commands (add, delete, clear mappings)
and table status request/reply to dump the current table along with switch
information.
Note that mappings should not be changed while they are in active use by
a flow. The result of doing so is undefined.
This only adds the OpenFlow infrastructure but doesn't actually
do anything with the information yet after the messages have been
decoded.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-06-02 15:11:00 -07:00
|
|
|
|
}
|
|
|
|
|
|
2015-09-09 17:33:42 +05:30
|
|
|
|
/* This function will print the request forward message. The reason for
|
|
|
|
|
* request forward is taken from rf.request.type */
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ofp_print_requestforward(struct ds *string, const struct ofp_header *oh,
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
const struct ofputil_port_map *port_map,
|
|
|
|
|
const struct ofputil_table_map *table_map)
|
2015-09-09 17:33:42 +05:30
|
|
|
|
{
|
|
|
|
|
struct ofputil_requestforward rf;
|
|
|
|
|
enum ofperr error;
|
|
|
|
|
|
|
|
|
|
error = ofputil_decode_requestforward(oh, &rf);
|
|
|
|
|
if (error) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return error;
|
2015-09-09 17:33:42 +05:30
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ds_put_cstr(string, " reason=");
|
|
|
|
|
|
|
|
|
|
switch (rf.reason) {
|
|
|
|
|
case OFPRFR_GROUP_MOD:
|
|
|
|
|
ds_put_cstr(string, "group_mod");
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
ofp_print_group_mod__(string, oh->version, rf.group_mod, port_map,
|
|
|
|
|
table_map);
|
2015-09-09 17:33:42 +05:30
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case OFPRFR_METER_MOD:
|
|
|
|
|
ds_put_cstr(string, "meter_mod");
|
|
|
|
|
ofp_print_meter_mod__(string, rf.meter_mod);
|
|
|
|
|
break;
|
2015-11-30 16:52:47 +05:30
|
|
|
|
|
|
|
|
|
case OFPRFR_N_REASONS:
|
|
|
|
|
OVS_NOT_REACHED();
|
2015-09-09 17:33:42 +05:30
|
|
|
|
}
|
|
|
|
|
ofputil_destroy_requestforward(&rf);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
|
|
|
|
|
return 0;
|
2015-09-09 17:33:42 +05:30
|
|
|
|
}
|
|
|
|
|
|
ipfix: Add support for exporting ipfix statistics.
It is meaningful for user to check the stats of IPFIX.
Using IPFIX stats, user can know how much flows the system
can support. It is also can be used for performance check
of IPFIX.
IPFIX stats is added for per IPFIX exporter. If bridge IPFIX is
enabled on the bridge, the whole bridge will have one exporter.
For flow IPFIX, the system keeps per id (column in
Flow_Sample_Collector_Set) per exporter.
1) Add 'ovs-ofctl dump-ipfix-bridge SWITCH' to export IPFIX stats of
the bridge which enable bridge IPFIX. The output format:
NXST_IPFIX_BRIDGE reply (xid=0x2):
bridge ipfix: flows=0, current flows=0, sampled pkts=0, \
ipv4 ok=0, ipv6 ok=0, tx pkts=0
pkts errs=0, ipv4 errs=0, ipv6 errs=0, tx errs=0
2) Add 'ovs-ofctl dump-ipfix-flow SWITCH' to export IPFIX stats of
the bridge which enable flow IPFIX. The output format:
NXST_IPFIX_FLOW reply (xid=0x2): 2 ids
id 1: flows=4, current flows=4, sampled pkts=14, ipv4 ok=13, \
ipv6 ok=0, tx pkts=0
pkts errs=0, ipv4 errs=0, ipv6 errs=0, tx errs=0
id 2: flows=0, current flows=0, sampled pkts=0, ipv4 ok=0, \
ipv6 ok=0, tx pkts=0
pkts errs=0, ipv4 errs=0, ipv6 errs=0, tx errs=0
flows: the number of total flow records, including those exported.
current flows: the number of current flow records cached.
sampled pkts: Successfully sampled packet count.
ipv4 ok: successfully sampled IPv4 flow packet count.
ipv6 ok: Successfully sampled IPv6 flow packet count.
tx pkts: the count of IPFIX exported packets sent to the collector(s).
pkts errs: count of packets failed when sampling, maybe not supported or other error.
ipv4 errs: Count of IPV4 flow packet in the error packets.
ipv6 errs: Count of IPV6 flow packet in the error packets.
tx errs: the count of IPFIX exported packets failed when sending to the collector(s).
Signed-off-by: Benli Ye <daniely@vmware.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
2016-06-13 14:44:09 -07:00
|
|
|
|
static void
|
|
|
|
|
print_ipfix_stat(struct ds *string, const char *leader, uint64_t stat, int more)
|
|
|
|
|
{
|
|
|
|
|
ds_put_cstr(string, leader);
|
|
|
|
|
if (stat != UINT64_MAX) {
|
|
|
|
|
ds_put_format(string, "%"PRIu64, stat);
|
|
|
|
|
} else {
|
|
|
|
|
ds_put_char(string, '?');
|
|
|
|
|
}
|
|
|
|
|
if (more) {
|
|
|
|
|
ds_put_cstr(string, ", ");
|
|
|
|
|
} else {
|
|
|
|
|
ds_put_cstr(string, "\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
ipfix: Add support for exporting ipfix statistics.
It is meaningful for user to check the stats of IPFIX.
Using IPFIX stats, user can know how much flows the system
can support. It is also can be used for performance check
of IPFIX.
IPFIX stats is added for per IPFIX exporter. If bridge IPFIX is
enabled on the bridge, the whole bridge will have one exporter.
For flow IPFIX, the system keeps per id (column in
Flow_Sample_Collector_Set) per exporter.
1) Add 'ovs-ofctl dump-ipfix-bridge SWITCH' to export IPFIX stats of
the bridge which enable bridge IPFIX. The output format:
NXST_IPFIX_BRIDGE reply (xid=0x2):
bridge ipfix: flows=0, current flows=0, sampled pkts=0, \
ipv4 ok=0, ipv6 ok=0, tx pkts=0
pkts errs=0, ipv4 errs=0, ipv6 errs=0, tx errs=0
2) Add 'ovs-ofctl dump-ipfix-flow SWITCH' to export IPFIX stats of
the bridge which enable flow IPFIX. The output format:
NXST_IPFIX_FLOW reply (xid=0x2): 2 ids
id 1: flows=4, current flows=4, sampled pkts=14, ipv4 ok=13, \
ipv6 ok=0, tx pkts=0
pkts errs=0, ipv4 errs=0, ipv6 errs=0, tx errs=0
id 2: flows=0, current flows=0, sampled pkts=0, ipv4 ok=0, \
ipv6 ok=0, tx pkts=0
pkts errs=0, ipv4 errs=0, ipv6 errs=0, tx errs=0
flows: the number of total flow records, including those exported.
current flows: the number of current flow records cached.
sampled pkts: Successfully sampled packet count.
ipv4 ok: successfully sampled IPv4 flow packet count.
ipv6 ok: Successfully sampled IPv6 flow packet count.
tx pkts: the count of IPFIX exported packets sent to the collector(s).
pkts errs: count of packets failed when sampling, maybe not supported or other error.
ipv4 errs: Count of IPV4 flow packet in the error packets.
ipv6 errs: Count of IPV6 flow packet in the error packets.
tx errs: the count of IPFIX exported packets failed when sending to the collector(s).
Signed-off-by: Benli Ye <daniely@vmware.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
2016-06-13 14:44:09 -07:00
|
|
|
|
ofp_print_nxst_ipfix_bridge_reply(struct ds *string, const struct ofp_header *oh)
|
|
|
|
|
{
|
|
|
|
|
struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
|
|
|
|
|
for (;;) {
|
|
|
|
|
struct ofputil_ipfix_stats is;
|
|
|
|
|
int retval;
|
|
|
|
|
|
|
|
|
|
retval = ofputil_pull_ipfix_stats(&is, &b);
|
|
|
|
|
if (retval) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return retval != EOF ? retval : 0;
|
ipfix: Add support for exporting ipfix statistics.
It is meaningful for user to check the stats of IPFIX.
Using IPFIX stats, user can know how much flows the system
can support. It is also can be used for performance check
of IPFIX.
IPFIX stats is added for per IPFIX exporter. If bridge IPFIX is
enabled on the bridge, the whole bridge will have one exporter.
For flow IPFIX, the system keeps per id (column in
Flow_Sample_Collector_Set) per exporter.
1) Add 'ovs-ofctl dump-ipfix-bridge SWITCH' to export IPFIX stats of
the bridge which enable bridge IPFIX. The output format:
NXST_IPFIX_BRIDGE reply (xid=0x2):
bridge ipfix: flows=0, current flows=0, sampled pkts=0, \
ipv4 ok=0, ipv6 ok=0, tx pkts=0
pkts errs=0, ipv4 errs=0, ipv6 errs=0, tx errs=0
2) Add 'ovs-ofctl dump-ipfix-flow SWITCH' to export IPFIX stats of
the bridge which enable flow IPFIX. The output format:
NXST_IPFIX_FLOW reply (xid=0x2): 2 ids
id 1: flows=4, current flows=4, sampled pkts=14, ipv4 ok=13, \
ipv6 ok=0, tx pkts=0
pkts errs=0, ipv4 errs=0, ipv6 errs=0, tx errs=0
id 2: flows=0, current flows=0, sampled pkts=0, ipv4 ok=0, \
ipv6 ok=0, tx pkts=0
pkts errs=0, ipv4 errs=0, ipv6 errs=0, tx errs=0
flows: the number of total flow records, including those exported.
current flows: the number of current flow records cached.
sampled pkts: Successfully sampled packet count.
ipv4 ok: successfully sampled IPv4 flow packet count.
ipv6 ok: Successfully sampled IPv6 flow packet count.
tx pkts: the count of IPFIX exported packets sent to the collector(s).
pkts errs: count of packets failed when sampling, maybe not supported or other error.
ipv4 errs: Count of IPV4 flow packet in the error packets.
ipv6 errs: Count of IPV6 flow packet in the error packets.
tx errs: the count of IPFIX exported packets failed when sending to the collector(s).
Signed-off-by: Benli Ye <daniely@vmware.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
2016-06-13 14:44:09 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ds_put_cstr(string, "\n bridge ipfix: ");
|
|
|
|
|
print_ipfix_stat(string, "flows=", is.total_flows, 1);
|
|
|
|
|
print_ipfix_stat(string, "current flows=", is.current_flows, 1);
|
|
|
|
|
print_ipfix_stat(string, "sampled pkts=", is.pkts, 1);
|
|
|
|
|
print_ipfix_stat(string, "ipv4 ok=", is.ipv4_pkts, 1);
|
|
|
|
|
print_ipfix_stat(string, "ipv6 ok=", is.ipv6_pkts, 1);
|
|
|
|
|
print_ipfix_stat(string, "tx pkts=", is.tx_pkts, 0);
|
|
|
|
|
ds_put_cstr(string, " ");
|
|
|
|
|
print_ipfix_stat(string, "pkts errs=", is.error_pkts, 1);
|
|
|
|
|
print_ipfix_stat(string, "ipv4 errs=", is.ipv4_error_pkts, 1);
|
|
|
|
|
print_ipfix_stat(string, "ipv6 errs=", is.ipv6_error_pkts, 1);
|
|
|
|
|
print_ipfix_stat(string, "tx errs=", is.tx_errors, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
ipfix: Add support for exporting ipfix statistics.
It is meaningful for user to check the stats of IPFIX.
Using IPFIX stats, user can know how much flows the system
can support. It is also can be used for performance check
of IPFIX.
IPFIX stats is added for per IPFIX exporter. If bridge IPFIX is
enabled on the bridge, the whole bridge will have one exporter.
For flow IPFIX, the system keeps per id (column in
Flow_Sample_Collector_Set) per exporter.
1) Add 'ovs-ofctl dump-ipfix-bridge SWITCH' to export IPFIX stats of
the bridge which enable bridge IPFIX. The output format:
NXST_IPFIX_BRIDGE reply (xid=0x2):
bridge ipfix: flows=0, current flows=0, sampled pkts=0, \
ipv4 ok=0, ipv6 ok=0, tx pkts=0
pkts errs=0, ipv4 errs=0, ipv6 errs=0, tx errs=0
2) Add 'ovs-ofctl dump-ipfix-flow SWITCH' to export IPFIX stats of
the bridge which enable flow IPFIX. The output format:
NXST_IPFIX_FLOW reply (xid=0x2): 2 ids
id 1: flows=4, current flows=4, sampled pkts=14, ipv4 ok=13, \
ipv6 ok=0, tx pkts=0
pkts errs=0, ipv4 errs=0, ipv6 errs=0, tx errs=0
id 2: flows=0, current flows=0, sampled pkts=0, ipv4 ok=0, \
ipv6 ok=0, tx pkts=0
pkts errs=0, ipv4 errs=0, ipv6 errs=0, tx errs=0
flows: the number of total flow records, including those exported.
current flows: the number of current flow records cached.
sampled pkts: Successfully sampled packet count.
ipv4 ok: successfully sampled IPv4 flow packet count.
ipv6 ok: Successfully sampled IPv6 flow packet count.
tx pkts: the count of IPFIX exported packets sent to the collector(s).
pkts errs: count of packets failed when sampling, maybe not supported or other error.
ipv4 errs: Count of IPV4 flow packet in the error packets.
ipv6 errs: Count of IPV6 flow packet in the error packets.
tx errs: the count of IPFIX exported packets failed when sending to the collector(s).
Signed-off-by: Benli Ye <daniely@vmware.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
2016-06-13 14:44:09 -07:00
|
|
|
|
ofp_print_nxst_ipfix_flow_reply(struct ds *string, const struct ofp_header *oh)
|
|
|
|
|
{
|
|
|
|
|
ds_put_format(string, " %"PRIuSIZE" ids\n", ofputil_count_ipfix_stats(oh));
|
|
|
|
|
|
|
|
|
|
struct ofpbuf b = ofpbuf_const_initializer(oh, ntohs(oh->length));
|
|
|
|
|
for (;;) {
|
|
|
|
|
struct ofputil_ipfix_stats is;
|
|
|
|
|
int retval;
|
|
|
|
|
|
|
|
|
|
retval = ofputil_pull_ipfix_stats(&is, &b);
|
|
|
|
|
if (retval) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return retval != EOF ? retval : 0;
|
ipfix: Add support for exporting ipfix statistics.
It is meaningful for user to check the stats of IPFIX.
Using IPFIX stats, user can know how much flows the system
can support. It is also can be used for performance check
of IPFIX.
IPFIX stats is added for per IPFIX exporter. If bridge IPFIX is
enabled on the bridge, the whole bridge will have one exporter.
For flow IPFIX, the system keeps per id (column in
Flow_Sample_Collector_Set) per exporter.
1) Add 'ovs-ofctl dump-ipfix-bridge SWITCH' to export IPFIX stats of
the bridge which enable bridge IPFIX. The output format:
NXST_IPFIX_BRIDGE reply (xid=0x2):
bridge ipfix: flows=0, current flows=0, sampled pkts=0, \
ipv4 ok=0, ipv6 ok=0, tx pkts=0
pkts errs=0, ipv4 errs=0, ipv6 errs=0, tx errs=0
2) Add 'ovs-ofctl dump-ipfix-flow SWITCH' to export IPFIX stats of
the bridge which enable flow IPFIX. The output format:
NXST_IPFIX_FLOW reply (xid=0x2): 2 ids
id 1: flows=4, current flows=4, sampled pkts=14, ipv4 ok=13, \
ipv6 ok=0, tx pkts=0
pkts errs=0, ipv4 errs=0, ipv6 errs=0, tx errs=0
id 2: flows=0, current flows=0, sampled pkts=0, ipv4 ok=0, \
ipv6 ok=0, tx pkts=0
pkts errs=0, ipv4 errs=0, ipv6 errs=0, tx errs=0
flows: the number of total flow records, including those exported.
current flows: the number of current flow records cached.
sampled pkts: Successfully sampled packet count.
ipv4 ok: successfully sampled IPv4 flow packet count.
ipv6 ok: Successfully sampled IPv6 flow packet count.
tx pkts: the count of IPFIX exported packets sent to the collector(s).
pkts errs: count of packets failed when sampling, maybe not supported or other error.
ipv4 errs: Count of IPV4 flow packet in the error packets.
ipv6 errs: Count of IPV6 flow packet in the error packets.
tx errs: the count of IPFIX exported packets failed when sending to the collector(s).
Signed-off-by: Benli Ye <daniely@vmware.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
2016-06-13 14:44:09 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ds_put_cstr(string, " id");
|
|
|
|
|
ds_put_format(string, " %3"PRIuSIZE": ", (size_t) is.collector_set_id);
|
|
|
|
|
print_ipfix_stat(string, "flows=", is.total_flows, 1);
|
|
|
|
|
print_ipfix_stat(string, "current flows=", is.current_flows, 1);
|
|
|
|
|
print_ipfix_stat(string, "sampled pkts=", is.pkts, 1);
|
|
|
|
|
print_ipfix_stat(string, "ipv4 ok=", is.ipv4_pkts, 1);
|
|
|
|
|
print_ipfix_stat(string, "ipv6 ok=", is.ipv6_pkts, 1);
|
|
|
|
|
print_ipfix_stat(string, "tx pkts=", is.tx_pkts, 0);
|
|
|
|
|
ds_put_cstr(string, " ");
|
|
|
|
|
print_ipfix_stat(string, "pkts errs=", is.error_pkts, 1);
|
|
|
|
|
print_ipfix_stat(string, "ipv4 errs=", is.ipv4_error_pkts, 1);
|
|
|
|
|
print_ipfix_stat(string, "ipv6 errs=", is.ipv6_error_pkts, 1);
|
|
|
|
|
print_ipfix_stat(string, "tx errs=", is.tx_errors, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2016-08-18 14:09:41 -07:00
|
|
|
|
ofp_print_nxt_ct_flush_zone(struct ds *string, const struct nx_zone_id *nzi)
|
|
|
|
|
{
|
|
|
|
|
ds_put_format(string, " zone_id=%"PRIu16, ntohs(nzi->zone_id));
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return 0;
|
2016-08-18 14:09:41 -07:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
static enum ofperr
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ofp_to_string__(const struct ofp_header *oh,
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
const struct ofputil_port_map *port_map,
|
|
|
|
|
const struct ofputil_table_map *table_map, enum ofpraw raw,
|
2012-07-19 23:23:17 -07:00
|
|
|
|
struct ds *string, int verbosity)
|
2012-07-12 13:32:47 -07:00
|
|
|
|
{
|
|
|
|
|
const void *msg = oh;
|
2016-01-14 22:16:34 -08:00
|
|
|
|
enum ofptype type = ofptype_from_ofpraw(raw);
|
|
|
|
|
switch (type) {
|
2013-06-28 13:41:53 -07:00
|
|
|
|
case OFPTYPE_GROUP_STATS_REQUEST:
|
2014-05-27 18:05:37 +09:00
|
|
|
|
ofp_print_stats(string, oh);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_ofpst_group_request(string, oh);
|
2013-09-01 18:30:17 -07:00
|
|
|
|
|
2013-06-28 13:41:53 -07:00
|
|
|
|
case OFPTYPE_GROUP_STATS_REPLY:
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_group_stats(string, oh);
|
2013-09-01 18:30:17 -07:00
|
|
|
|
|
2013-06-28 13:41:53 -07:00
|
|
|
|
case OFPTYPE_GROUP_DESC_STATS_REQUEST:
|
2014-05-27 18:05:37 +09:00
|
|
|
|
ofp_print_stats(string, oh);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_ofpst_group_desc_request(string, oh);
|
2013-09-01 18:30:17 -07:00
|
|
|
|
|
2013-06-28 13:41:53 -07:00
|
|
|
|
case OFPTYPE_GROUP_DESC_STATS_REPLY:
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
return ofp_print_group_desc(string, oh, port_map, table_map);
|
2013-09-01 18:30:17 -07:00
|
|
|
|
|
2013-06-28 13:41:53 -07:00
|
|
|
|
case OFPTYPE_GROUP_FEATURES_STATS_REQUEST:
|
2014-05-27 18:05:37 +09:00
|
|
|
|
ofp_print_stats(string, oh);
|
2013-09-01 18:30:17 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2013-06-28 13:41:53 -07:00
|
|
|
|
case OFPTYPE_GROUP_FEATURES_STATS_REPLY:
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_group_features(string, oh);
|
2013-09-01 18:30:17 -07:00
|
|
|
|
|
|
|
|
|
case OFPTYPE_GROUP_MOD:
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
return ofp_print_group_mod(string, oh, port_map, table_map);
|
2013-09-01 18:30:17 -07:00
|
|
|
|
|
2013-06-28 13:41:53 -07:00
|
|
|
|
case OFPTYPE_TABLE_FEATURES_STATS_REQUEST:
|
|
|
|
|
case OFPTYPE_TABLE_FEATURES_STATS_REPLY:
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
return ofp_print_table_features_reply(string, oh, table_map);
|
2012-11-27 17:44:22 +02:00
|
|
|
|
|
2015-07-02 20:35:44 -07:00
|
|
|
|
case OFPTYPE_TABLE_DESC_REQUEST:
|
|
|
|
|
case OFPTYPE_TABLE_DESC_REPLY:
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
return ofp_print_table_desc_reply(string, oh, table_map);
|
2015-07-02 20:35:44 -07:00
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_HELLO:
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_hello(string, oh);
|
2010-12-06 10:20:20 -08:00
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_ERROR:
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
return ofp_print_error_msg(string, oh, port_map, table_map);
|
2010-12-06 10:20:20 -08:00
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_ECHO_REQUEST:
|
|
|
|
|
case OFPTYPE_ECHO_REPLY:
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_echo(string, oh, verbosity);
|
2010-12-06 10:20:20 -08:00
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_FEATURES_REQUEST:
|
2010-12-06 10:20:20 -08:00
|
|
|
|
break;
|
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_FEATURES_REPLY:
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_switch_features(string, oh);
|
2010-12-06 10:20:20 -08:00
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_GET_CONFIG_REQUEST:
|
2010-12-06 10:20:20 -08:00
|
|
|
|
break;
|
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_GET_CONFIG_REPLY:
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_get_config_reply(string, oh);
|
2015-12-21 15:39:10 -08:00
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_SET_CONFIG:
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_set_config(string, oh);
|
2010-12-06 10:20:20 -08:00
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_PACKET_IN:
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
return ofp_print_packet_in(string, oh, port_map, table_map, verbosity);
|
2010-12-06 10:20:20 -08:00
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_FLOW_REMOVED:
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
return ofp_print_flow_removed(string, oh, port_map, table_map);
|
2010-12-06 10:20:20 -08:00
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_PORT_STATUS:
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_port_status(string, oh);
|
2010-12-06 10:20:20 -08:00
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_PACKET_OUT:
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
return ofp_print_packet_out(string, oh, port_map, table_map,
|
|
|
|
|
verbosity);
|
2010-12-06 10:20:20 -08:00
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_FLOW_MOD:
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
return ofp_print_flow_mod(string, oh, port_map, table_map, verbosity);
|
2010-12-06 10:20:20 -08:00
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_PORT_MOD:
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_port_mod(string, oh, port_map);
|
2010-12-06 10:20:20 -08:00
|
|
|
|
|
2013-09-07 03:02:32 -07:00
|
|
|
|
case OFPTYPE_TABLE_MOD:
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
return ofp_print_table_mod(string, oh, table_map);
|
2013-09-07 03:02:32 -07:00
|
|
|
|
|
2013-06-20 17:26:18 +03:00
|
|
|
|
case OFPTYPE_METER_MOD:
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_meter_mod(string, oh);
|
2013-06-20 17:26:18 +03:00
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_BARRIER_REQUEST:
|
|
|
|
|
case OFPTYPE_BARRIER_REPLY:
|
2010-12-06 10:20:20 -08:00
|
|
|
|
break;
|
|
|
|
|
|
2013-10-24 15:54:03 -07:00
|
|
|
|
case OFPTYPE_QUEUE_GET_CONFIG_REQUEST:
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_queue_get_config_request(string, oh, port_map);
|
2013-10-24 15:54:03 -07:00
|
|
|
|
|
|
|
|
|
case OFPTYPE_QUEUE_GET_CONFIG_REPLY:
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_queue_get_config_reply(string, oh, port_map);
|
2013-10-24 15:54:03 -07:00
|
|
|
|
|
2012-12-28 18:28:49 +02:00
|
|
|
|
case OFPTYPE_ROLE_REQUEST:
|
|
|
|
|
case OFPTYPE_ROLE_REPLY:
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_role_message(string, oh);
|
2013-10-22 11:40:02 +03:00
|
|
|
|
case OFPTYPE_ROLE_STATUS:
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_role_status_message(string, oh);
|
2012-12-28 18:28:49 +02:00
|
|
|
|
|
2015-09-09 17:33:42 +05:30
|
|
|
|
case OFPTYPE_REQUESTFORWARD:
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
return ofp_print_requestforward(string, oh, port_map, table_map);
|
2015-09-09 17:33:42 +05:30
|
|
|
|
|
2016-02-18 15:54:26 +05:30
|
|
|
|
case OFPTYPE_TABLE_STATUS:
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
return ofp_print_table_status_message(string, oh, table_map);
|
2016-02-18 15:54:26 +05:30
|
|
|
|
|
2013-06-28 13:41:53 -07:00
|
|
|
|
case OFPTYPE_METER_STATS_REQUEST:
|
|
|
|
|
case OFPTYPE_METER_CONFIG_STATS_REQUEST:
|
2014-05-27 18:05:37 +09:00
|
|
|
|
ofp_print_stats(string, oh);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_meter_stats_request(string, oh);
|
2013-06-20 17:26:18 +03:00
|
|
|
|
|
2013-06-28 13:41:53 -07:00
|
|
|
|
case OFPTYPE_METER_STATS_REPLY:
|
2014-05-27 18:05:37 +09:00
|
|
|
|
ofp_print_stats(string, oh);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_meter_stats_reply(string, oh);
|
2013-06-20 17:26:18 +03:00
|
|
|
|
|
2013-06-28 13:41:53 -07:00
|
|
|
|
case OFPTYPE_METER_CONFIG_STATS_REPLY:
|
2014-05-27 18:05:37 +09:00
|
|
|
|
ofp_print_stats(string, oh);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_meter_config_reply(string, oh);
|
2013-06-20 17:26:18 +03:00
|
|
|
|
|
2013-06-28 13:41:53 -07:00
|
|
|
|
case OFPTYPE_METER_FEATURES_STATS_REPLY:
|
2014-05-27 18:05:37 +09:00
|
|
|
|
ofp_print_stats(string, oh);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_meter_features_reply(string, oh);
|
2013-06-20 17:26:18 +03:00
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_DESC_STATS_REQUEST:
|
2013-06-28 13:41:53 -07:00
|
|
|
|
case OFPTYPE_METER_FEATURES_STATS_REQUEST:
|
2014-05-27 18:05:37 +09:00
|
|
|
|
ofp_print_stats(string, oh);
|
2010-12-06 10:20:20 -08:00
|
|
|
|
break;
|
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_FLOW_STATS_REQUEST:
|
|
|
|
|
case OFPTYPE_AGGREGATE_STATS_REQUEST:
|
2014-05-27 18:05:37 +09:00
|
|
|
|
ofp_print_stats(string, oh);
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
return ofp_print_flow_stats_request(string, oh, port_map, table_map);
|
2010-12-06 10:20:20 -08:00
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_TABLE_STATS_REQUEST:
|
2014-05-27 18:05:37 +09:00
|
|
|
|
ofp_print_stats(string, oh);
|
2010-12-06 10:20:20 -08:00
|
|
|
|
break;
|
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_PORT_STATS_REQUEST:
|
2014-05-27 18:05:37 +09:00
|
|
|
|
ofp_print_stats(string, oh);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_ofpst_port_request(string, oh, port_map);
|
2010-12-06 10:20:20 -08:00
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_QUEUE_STATS_REQUEST:
|
2014-05-27 18:05:37 +09:00
|
|
|
|
ofp_print_stats(string, oh);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_ofpst_queue_request(string, oh, port_map);
|
2010-12-06 10:20:20 -08:00
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_DESC_STATS_REPLY:
|
2014-05-27 18:05:37 +09:00
|
|
|
|
ofp_print_stats(string, oh);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_ofpst_desc_reply(string, oh);
|
2010-12-06 10:20:20 -08:00
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_FLOW_STATS_REPLY:
|
2014-05-27 18:05:37 +09:00
|
|
|
|
ofp_print_stats(string, oh);
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
return ofp_print_flow_stats_reply(string, oh, port_map, table_map);
|
2010-12-06 10:20:20 -08:00
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_QUEUE_STATS_REPLY:
|
2014-05-27 18:05:37 +09:00
|
|
|
|
ofp_print_stats(string, oh);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_ofpst_queue_reply(string, oh, port_map, verbosity);
|
2010-12-06 10:20:20 -08:00
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_PORT_STATS_REPLY:
|
2014-05-27 18:05:37 +09:00
|
|
|
|
ofp_print_stats(string, oh);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_ofpst_port_reply(string, oh, port_map, verbosity);
|
2010-12-06 10:20:20 -08:00
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_TABLE_STATS_REPLY:
|
2014-05-27 18:05:37 +09:00
|
|
|
|
ofp_print_stats(string, oh);
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
return ofp_print_table_stats_reply(string, oh, table_map);
|
2010-12-06 10:20:20 -08:00
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_AGGREGATE_STATS_REPLY:
|
2014-05-27 18:05:37 +09:00
|
|
|
|
ofp_print_stats(string, oh);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_aggregate_stats_reply(string, oh);
|
2009-07-08 13:19:16 -07:00
|
|
|
|
|
2014-05-07 23:18:46 -07:00
|
|
|
|
case OFPTYPE_PORT_DESC_STATS_REQUEST:
|
2014-05-27 18:05:37 +09:00
|
|
|
|
ofp_print_stats(string, oh);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_ofpst_port_desc_request(string, oh, port_map);
|
2014-05-07 23:18:46 -07:00
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_PORT_DESC_STATS_REPLY:
|
2014-05-27 18:05:37 +09:00
|
|
|
|
ofp_print_stats(string, oh);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_ofpst_port_desc_reply(string, oh);
|
2012-05-04 14:42:04 -07:00
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_FLOW_MOD_TABLE_ID:
|
2018-02-15 14:38:28 -08:00
|
|
|
|
return ofp_print_nxt_flow_mod_table_id(string, oh);
|
2011-05-12 09:58:01 -07:00
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_SET_FLOW_FORMAT:
|
2018-02-15 14:38:28 -08:00
|
|
|
|
return ofp_print_nxt_set_flow_format(string, oh);
|
2010-12-07 13:22:46 -08:00
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_SET_PACKET_IN_FORMAT:
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_nxt_set_packet_in_format(string, ofpmsg_body(oh));
|
2011-12-09 15:48:26 -08:00
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_FLOW_AGE:
|
2012-02-07 10:13:52 -08:00
|
|
|
|
break;
|
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_SET_CONTROLLER_ID:
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_nxt_set_controller_id(string, ofpmsg_body(oh));
|
2012-02-09 14:17:33 -08:00
|
|
|
|
|
2013-09-07 15:36:22 +03:00
|
|
|
|
case OFPTYPE_GET_ASYNC_REPLY:
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_SET_ASYNC_CONFIG:
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_set_async_config(string, oh, type);
|
2013-09-07 15:36:22 +03:00
|
|
|
|
case OFPTYPE_GET_ASYNC_REQUEST:
|
|
|
|
|
break;
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_FLOW_MONITOR_CANCEL:
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_nxt_flow_monitor_cancel(string, msg);
|
2012-07-12 14:18:05 -07:00
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_FLOW_MONITOR_PAUSED:
|
|
|
|
|
case OFPTYPE_FLOW_MONITOR_RESUMED:
|
2012-07-12 14:18:05 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_FLOW_MONITOR_STATS_REQUEST:
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
return ofp_print_nxst_flow_monitor_request(string, msg, port_map,
|
|
|
|
|
table_map);
|
2012-07-12 14:18:05 -07:00
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
case OFPTYPE_FLOW_MONITOR_STATS_REPLY:
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
return ofp_print_nxst_flow_monitor_reply(string, msg, port_map,
|
|
|
|
|
table_map);
|
2014-05-02 09:54:27 +03:00
|
|
|
|
|
|
|
|
|
case OFPTYPE_BUNDLE_CONTROL:
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_bundle_ctrl(string, msg);
|
2014-05-02 09:54:27 +03:00
|
|
|
|
|
|
|
|
|
case OFPTYPE_BUNDLE_ADD_MESSAGE:
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
return ofp_print_bundle_add(string, msg, port_map, table_map,
|
|
|
|
|
verbosity);
|
openflow: Table maintenance commands for Geneve options.
In order to work with Geneve options, we need to maintain a mapping
table between an option (defined by <class, type, length>) and
an NXM field that can be operated on for the purposes of matches,
actions, etc. This mapping must be explicitly specified by the
user.
Conceptually, this table could be communicated using either OpenFlow
or OVSDB. Using OVSDB requires less code and definition of extensions
than OpenFlow but introduces the possibility that mapping table
updates and flow modifications are desynchronized from each other.
This is dangerous because the mapping table signifcantly impacts the
way that flows using Geneve options are installed and processed by
OVS. Therefore, the mapping table is maintained using OpenFlow commands
instead, which opens the possibility of using synchronization between
table changes and flow modifications through barriers, bundles, etc.
There are two primary groups of OpenFlow messages that are introduced
as Nicira extensions: modification commands (add, delete, clear mappings)
and table status request/reply to dump the current table along with switch
information.
Note that mappings should not be changed while they are in active use by
a flow. The result of doing so is undefined.
This only adds the OpenFlow infrastructure but doesn't actually
do anything with the information yet after the messages have been
decoded.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-06-02 15:11:00 -07:00
|
|
|
|
|
2015-12-16 02:47:50 +08:00
|
|
|
|
case OFPTYPE_NXT_TLV_TABLE_MOD:
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_tlv_table_mod(string, msg);
|
openflow: Table maintenance commands for Geneve options.
In order to work with Geneve options, we need to maintain a mapping
table between an option (defined by <class, type, length>) and
an NXM field that can be operated on for the purposes of matches,
actions, etc. This mapping must be explicitly specified by the
user.
Conceptually, this table could be communicated using either OpenFlow
or OVSDB. Using OVSDB requires less code and definition of extensions
than OpenFlow but introduces the possibility that mapping table
updates and flow modifications are desynchronized from each other.
This is dangerous because the mapping table signifcantly impacts the
way that flows using Geneve options are installed and processed by
OVS. Therefore, the mapping table is maintained using OpenFlow commands
instead, which opens the possibility of using synchronization between
table changes and flow modifications through barriers, bundles, etc.
There are two primary groups of OpenFlow messages that are introduced
as Nicira extensions: modification commands (add, delete, clear mappings)
and table status request/reply to dump the current table along with switch
information.
Note that mappings should not be changed while they are in active use by
a flow. The result of doing so is undefined.
This only adds the OpenFlow infrastructure but doesn't actually
do anything with the information yet after the messages have been
decoded.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-06-02 15:11:00 -07:00
|
|
|
|
|
2015-12-16 02:47:50 +08:00
|
|
|
|
case OFPTYPE_NXT_TLV_TABLE_REQUEST:
|
openflow: Table maintenance commands for Geneve options.
In order to work with Geneve options, we need to maintain a mapping
table between an option (defined by <class, type, length>) and
an NXM field that can be operated on for the purposes of matches,
actions, etc. This mapping must be explicitly specified by the
user.
Conceptually, this table could be communicated using either OpenFlow
or OVSDB. Using OVSDB requires less code and definition of extensions
than OpenFlow but introduces the possibility that mapping table
updates and flow modifications are desynchronized from each other.
This is dangerous because the mapping table signifcantly impacts the
way that flows using Geneve options are installed and processed by
OVS. Therefore, the mapping table is maintained using OpenFlow commands
instead, which opens the possibility of using synchronization between
table changes and flow modifications through barriers, bundles, etc.
There are two primary groups of OpenFlow messages that are introduced
as Nicira extensions: modification commands (add, delete, clear mappings)
and table status request/reply to dump the current table along with switch
information.
Note that mappings should not be changed while they are in active use by
a flow. The result of doing so is undefined.
This only adds the OpenFlow infrastructure but doesn't actually
do anything with the information yet after the messages have been
decoded.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-06-02 15:11:00 -07:00
|
|
|
|
break;
|
|
|
|
|
|
2015-12-16 02:47:50 +08:00
|
|
|
|
case OFPTYPE_NXT_TLV_TABLE_REPLY:
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_tlv_table_reply(string, msg);
|
openflow: Table maintenance commands for Geneve options.
In order to work with Geneve options, we need to maintain a mapping
table between an option (defined by <class, type, length>) and
an NXM field that can be operated on for the purposes of matches,
actions, etc. This mapping must be explicitly specified by the
user.
Conceptually, this table could be communicated using either OpenFlow
or OVSDB. Using OVSDB requires less code and definition of extensions
than OpenFlow but introduces the possibility that mapping table
updates and flow modifications are desynchronized from each other.
This is dangerous because the mapping table signifcantly impacts the
way that flows using Geneve options are installed and processed by
OVS. Therefore, the mapping table is maintained using OpenFlow commands
instead, which opens the possibility of using synchronization between
table changes and flow modifications through barriers, bundles, etc.
There are two primary groups of OpenFlow messages that are introduced
as Nicira extensions: modification commands (add, delete, clear mappings)
and table status request/reply to dump the current table along with switch
information.
Note that mappings should not be changed while they are in active use by
a flow. The result of doing so is undefined.
This only adds the OpenFlow infrastructure but doesn't actually
do anything with the information yet after the messages have been
decoded.
Signed-off-by: Jesse Gross <jesse@nicira.com>
Acked-by: Ben Pfaff <blp@nicira.com>
2015-06-02 15:11:00 -07:00
|
|
|
|
|
Implement serializing the state of packet traversal in "continuations".
One purpose of OpenFlow packet-in messages is to allow a controller to
interpose on the path of a packet through the flow tables. If, for
example, the controller needs to modify a packet in some way that the
switch doesn't directly support, the controller should be able to
program the switch to send it the packet, then modify the packet and
send it back to the switch to continue through the flow table.
That's the theory. In practice, this doesn't work with any but the
simplest flow tables. Packet-in messages simply don't include enough
context to allow the flow table traversal to continue. For example:
* Via "resubmit" actions, an Open vSwitch packet can have an
effective "call stack", but a packet-in can't describe it, and
so it would be lost.
* A packet-in can't preserve the stack used by NXAST_PUSH and
NXAST_POP actions.
* A packet-in can't preserve the OpenFlow 1.1+ action set.
* A packet-in can't preserve the state of Open vSwitch mirroring
or connection tracking.
This commit introduces a solution called "continuations". A continuation
is the state of a packet's traversal through OpenFlow flow tables. A
"controller" action with the "pause" flag, which is newly implemented in
this commit, generates a continuation and sends it to the OpenFlow
controller in a packet-in asynchronous message (only NXT_PACKET_IN2
supports continuations, so the controller must configure them with
NXT_SET_PACKET_IN_FORMAT). The controller processes the packet-in,
possibly modifying some of its data, and sends it back to the switch with
an NXT_RESUME request, which causes flow table traversal to continue. In
principle, a single packet can be paused and resumed multiple times.
Another way to look at it is:
- "pause" is an extension of the existing OFPAT_CONTROLLER
action. It sends the packet to the controller, with full
pipeline context (some of which is switch implementation
dependent, and may thus vary from switch to switch).
- A continuation is an extension of OFPT_PACKET_IN, allowing for
implementation dependent metadata.
- NXT_RESUME is an extension of OFPT_PACKET_OUT, with the
semantics that the pipeline processing is continued with the
original translation context from where it was left at the time
it was paused.
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Jarno Rajahalme <jarno@ovn.org>
2016-02-19 16:10:06 -08:00
|
|
|
|
case OFPTYPE_NXT_RESUME:
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
return ofp_print_packet_in(string, msg, port_map, table_map,
|
|
|
|
|
verbosity);
|
ipfix: Add support for exporting ipfix statistics.
It is meaningful for user to check the stats of IPFIX.
Using IPFIX stats, user can know how much flows the system
can support. It is also can be used for performance check
of IPFIX.
IPFIX stats is added for per IPFIX exporter. If bridge IPFIX is
enabled on the bridge, the whole bridge will have one exporter.
For flow IPFIX, the system keeps per id (column in
Flow_Sample_Collector_Set) per exporter.
1) Add 'ovs-ofctl dump-ipfix-bridge SWITCH' to export IPFIX stats of
the bridge which enable bridge IPFIX. The output format:
NXST_IPFIX_BRIDGE reply (xid=0x2):
bridge ipfix: flows=0, current flows=0, sampled pkts=0, \
ipv4 ok=0, ipv6 ok=0, tx pkts=0
pkts errs=0, ipv4 errs=0, ipv6 errs=0, tx errs=0
2) Add 'ovs-ofctl dump-ipfix-flow SWITCH' to export IPFIX stats of
the bridge which enable flow IPFIX. The output format:
NXST_IPFIX_FLOW reply (xid=0x2): 2 ids
id 1: flows=4, current flows=4, sampled pkts=14, ipv4 ok=13, \
ipv6 ok=0, tx pkts=0
pkts errs=0, ipv4 errs=0, ipv6 errs=0, tx errs=0
id 2: flows=0, current flows=0, sampled pkts=0, ipv4 ok=0, \
ipv6 ok=0, tx pkts=0
pkts errs=0, ipv4 errs=0, ipv6 errs=0, tx errs=0
flows: the number of total flow records, including those exported.
current flows: the number of current flow records cached.
sampled pkts: Successfully sampled packet count.
ipv4 ok: successfully sampled IPv4 flow packet count.
ipv6 ok: Successfully sampled IPv6 flow packet count.
tx pkts: the count of IPFIX exported packets sent to the collector(s).
pkts errs: count of packets failed when sampling, maybe not supported or other error.
ipv4 errs: Count of IPV4 flow packet in the error packets.
ipv6 errs: Count of IPV6 flow packet in the error packets.
tx errs: the count of IPFIX exported packets failed when sending to the collector(s).
Signed-off-by: Benli Ye <daniely@vmware.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
2016-06-13 14:44:09 -07:00
|
|
|
|
case OFPTYPE_IPFIX_BRIDGE_STATS_REQUEST:
|
|
|
|
|
break;
|
|
|
|
|
case OFPTYPE_IPFIX_BRIDGE_STATS_REPLY:
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_nxst_ipfix_bridge_reply(string, oh);
|
ipfix: Add support for exporting ipfix statistics.
It is meaningful for user to check the stats of IPFIX.
Using IPFIX stats, user can know how much flows the system
can support. It is also can be used for performance check
of IPFIX.
IPFIX stats is added for per IPFIX exporter. If bridge IPFIX is
enabled on the bridge, the whole bridge will have one exporter.
For flow IPFIX, the system keeps per id (column in
Flow_Sample_Collector_Set) per exporter.
1) Add 'ovs-ofctl dump-ipfix-bridge SWITCH' to export IPFIX stats of
the bridge which enable bridge IPFIX. The output format:
NXST_IPFIX_BRIDGE reply (xid=0x2):
bridge ipfix: flows=0, current flows=0, sampled pkts=0, \
ipv4 ok=0, ipv6 ok=0, tx pkts=0
pkts errs=0, ipv4 errs=0, ipv6 errs=0, tx errs=0
2) Add 'ovs-ofctl dump-ipfix-flow SWITCH' to export IPFIX stats of
the bridge which enable flow IPFIX. The output format:
NXST_IPFIX_FLOW reply (xid=0x2): 2 ids
id 1: flows=4, current flows=4, sampled pkts=14, ipv4 ok=13, \
ipv6 ok=0, tx pkts=0
pkts errs=0, ipv4 errs=0, ipv6 errs=0, tx errs=0
id 2: flows=0, current flows=0, sampled pkts=0, ipv4 ok=0, \
ipv6 ok=0, tx pkts=0
pkts errs=0, ipv4 errs=0, ipv6 errs=0, tx errs=0
flows: the number of total flow records, including those exported.
current flows: the number of current flow records cached.
sampled pkts: Successfully sampled packet count.
ipv4 ok: successfully sampled IPv4 flow packet count.
ipv6 ok: Successfully sampled IPv6 flow packet count.
tx pkts: the count of IPFIX exported packets sent to the collector(s).
pkts errs: count of packets failed when sampling, maybe not supported or other error.
ipv4 errs: Count of IPV4 flow packet in the error packets.
ipv6 errs: Count of IPV6 flow packet in the error packets.
tx errs: the count of IPFIX exported packets failed when sending to the collector(s).
Signed-off-by: Benli Ye <daniely@vmware.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
2016-06-13 14:44:09 -07:00
|
|
|
|
case OFPTYPE_IPFIX_FLOW_STATS_REQUEST:
|
|
|
|
|
break;
|
|
|
|
|
case OFPTYPE_IPFIX_FLOW_STATS_REPLY:
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_nxst_ipfix_flow_reply(string, oh);
|
2016-08-18 14:09:41 -07:00
|
|
|
|
|
|
|
|
|
case OFPTYPE_CT_FLUSH_ZONE:
|
2018-01-04 22:40:01 -08:00
|
|
|
|
return ofp_print_nxt_ct_flush_zone(string, ofpmsg_body(oh));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
add_newline(struct ds *s)
|
|
|
|
|
{
|
|
|
|
|
if (s->length && s->string[s->length - 1] != '\n') {
|
|
|
|
|
ds_put_char(s, '\n');
|
2009-11-13 12:41:57 -08:00
|
|
|
|
}
|
2010-12-06 10:20:20 -08:00
|
|
|
|
}
|
2009-07-08 13:19:16 -07:00
|
|
|
|
|
|
|
|
|
/* Composes and returns a string representing the OpenFlow packet of 'len'
|
|
|
|
|
* bytes at 'oh' at the given 'verbosity' level. 0 is a minimal amount of
|
|
|
|
|
* verbosity and higher numbers increase verbosity. The caller is responsible
|
|
|
|
|
* for freeing the string. */
|
|
|
|
|
char *
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ofp_to_string(const void *oh_, size_t len,
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
const struct ofputil_port_map *port_map,
|
|
|
|
|
const struct ofputil_table_map *table_map,
|
|
|
|
|
int verbosity)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
|
|
|
|
struct ds string = DS_EMPTY_INITIALIZER;
|
|
|
|
|
const struct ofp_header *oh = oh_;
|
|
|
|
|
|
2010-12-13 16:27:20 -08:00
|
|
|
|
if (!len) {
|
|
|
|
|
ds_put_cstr(&string, "OpenFlow message is empty\n");
|
|
|
|
|
} else if (len < sizeof(struct ofp_header)) {
|
2013-11-25 23:38:48 -08:00
|
|
|
|
ds_put_format(&string, "OpenFlow packet too short (only %"PRIuSIZE" bytes):\n",
|
2010-12-13 16:27:20 -08:00
|
|
|
|
len);
|
2010-12-06 10:20:20 -08:00
|
|
|
|
} else if (ntohs(oh->length) > len) {
|
2012-05-23 09:33:22 -07:00
|
|
|
|
enum ofperr error;
|
2012-07-19 23:23:17 -07:00
|
|
|
|
enum ofpraw raw;
|
2012-05-23 09:33:22 -07:00
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
error = ofpraw_decode_partial(&raw, oh, len);
|
2012-05-23 09:33:22 -07:00
|
|
|
|
if (!error) {
|
2012-07-19 23:23:17 -07:00
|
|
|
|
ofp_header_to_string__(oh, raw, &string);
|
2012-05-23 09:33:22 -07:00
|
|
|
|
ds_put_char(&string, '\n');
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-06 10:20:20 -08:00
|
|
|
|
ds_put_format(&string,
|
2013-11-25 23:38:48 -08:00
|
|
|
|
"(***truncated to %"PRIuSIZE" bytes from %"PRIu16"***)\n",
|
2010-12-06 10:20:20 -08:00
|
|
|
|
len, ntohs(oh->length));
|
|
|
|
|
} else if (ntohs(oh->length) < len) {
|
|
|
|
|
ds_put_format(&string,
|
2013-11-25 23:38:48 -08:00
|
|
|
|
"(***only uses %"PRIu16" bytes out of %"PRIuSIZE"***)\n",
|
2010-12-06 10:20:20 -08:00
|
|
|
|
ntohs(oh->length), len);
|
|
|
|
|
} else {
|
2012-01-12 15:48:19 -08:00
|
|
|
|
enum ofperr error;
|
2012-07-19 23:23:17 -07:00
|
|
|
|
enum ofpraw raw;
|
2010-12-06 10:20:20 -08:00
|
|
|
|
|
2012-07-19 23:23:17 -07:00
|
|
|
|
error = ofpraw_decode(&raw, oh);
|
2010-12-06 10:20:20 -08:00
|
|
|
|
if (!error) {
|
2018-01-04 22:40:01 -08:00
|
|
|
|
ofp_header_to_string__(oh, raw, &string);
|
|
|
|
|
size_t header_len = string.length;
|
|
|
|
|
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
error = ofp_to_string__(oh, port_map, table_map,
|
|
|
|
|
raw, &string, verbosity);
|
2018-01-04 22:40:01 -08:00
|
|
|
|
if (error) {
|
|
|
|
|
if (string.length > header_len) {
|
|
|
|
|
ds_chomp(&string, ' ');
|
|
|
|
|
add_newline(&string);
|
|
|
|
|
} else {
|
|
|
|
|
ds_put_char(&string, ' ');
|
2010-12-07 13:22:46 -08:00
|
|
|
|
}
|
2018-01-04 22:40:01 -08:00
|
|
|
|
ofp_print_error(&string, error);
|
|
|
|
|
} else {
|
|
|
|
|
ds_chomp(&string, ' ');
|
2010-12-06 10:20:20 -08:00
|
|
|
|
}
|
2018-01-04 22:40:01 -08:00
|
|
|
|
} else {
|
|
|
|
|
ofp_print_error(&string, error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (verbosity >= 5 || error) {
|
|
|
|
|
add_newline(&string);
|
|
|
|
|
ds_put_hex_dump(&string, oh, len, 0, true);
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-04 22:40:01 -08:00
|
|
|
|
add_newline(&string);
|
|
|
|
|
return ds_steal_cstr(&string);
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
2010-12-06 10:20:20 -08:00
|
|
|
|
ds_put_hex_dump(&string, oh, len, 0, true);
|
|
|
|
|
return ds_steal_cstr(&string);
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2010-08-30 00:24:53 -07:00
|
|
|
|
print_and_free(FILE *stream, char *string)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
|
|
|
|
fputs(string, stream);
|
|
|
|
|
free(string);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Pretty-print the OpenFlow packet of 'len' bytes at 'oh' to 'stream' at the
|
|
|
|
|
* given 'verbosity' level. 0 is a minimal amount of verbosity and higher
|
|
|
|
|
* numbers increase verbosity. */
|
|
|
|
|
void
|
2017-05-31 16:06:12 -07:00
|
|
|
|
ofp_print(FILE *stream, const void *oh, size_t len,
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
const struct ofputil_port_map *port_map,
|
|
|
|
|
const struct ofputil_table_map *table_map, int verbosity)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
Support accepting and displaying table names in OVS tools.
OpenFlow has little-known support for naming tables. Open vSwitch has
supported table names for ages, but it has never used or displayed them
outside of commands dedicated to table manipulation. This commit adds
support for table names in ovs-ofctl. When a table has a name, it displays
that name in flows and actions, so that, for example, the following:
table=1, arp, actions=resubmit(,2)
might become:
table=ingress_acl, arp, actions=resubmit(,mac_learning)
given appropriately named tables.
For backward compatibility, only interactive ovs-ofctl commands by default
display table names; to display them in scripts, use the new --names
option.
This feature was inspired by a talk that Kei Nohguchi presented at Open
vSwitch 2017 Fall Conference.
CC: Kei Nohguchi <kei@nohguchi.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Acked-by: Mark Michelson <mmichels@redhat.com>
Reviewed-by: Yifeng Sun <pkusunyifeng@gmail.com>
2018-01-05 16:59:13 -08:00
|
|
|
|
print_and_free(stream, ofp_to_string(oh, len, port_map, table_map,
|
|
|
|
|
verbosity));
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Dumps the contents of the Ethernet frame in the 'len' bytes starting at
|
2011-12-21 12:59:28 -08:00
|
|
|
|
* 'data' to 'stream'. */
|
2009-07-08 13:19:16 -07:00
|
|
|
|
void
|
2017-04-25 16:29:59 +00:00
|
|
|
|
ofp_print_packet(FILE *stream, const void *data, size_t len,
|
|
|
|
|
ovs_be32 packet_type)
|
|
|
|
|
{
|
|
|
|
|
print_and_free(stream, ofp_packet_to_string(data, len, packet_type));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ofp_print_dp_packet(FILE *stream, const struct dp_packet *packet)
|
2009-07-08 13:19:16 -07:00
|
|
|
|
{
|
2017-04-25 16:29:59 +00:00
|
|
|
|
print_and_free(stream, ofp_dp_packet_to_string(packet));
|
2009-07-08 13:19:16 -07:00
|
|
|
|
}
|