mirror of
https://github.com/openvswitch/ovs
synced 2025-10-19 14:37:21 +00:00
ofproto-dpif: Add -generate option to ofproto/trace command.
This commit is contained in:
71
lib/flow.c
71
lib/flow.c
@@ -888,3 +888,74 @@ flow_hash_fields_valid(enum nx_hash_fields fields)
|
||||
return fields == NX_HASH_FIELDS_ETH_SRC
|
||||
|| fields == NX_HASH_FIELDS_SYMMETRIC_L4;
|
||||
}
|
||||
|
||||
/* Puts into 'b' a packet that flow_extract() would parse as having the given
|
||||
* 'flow'.
|
||||
*
|
||||
* (This is useful only for testing, obviously, and the packet isn't really
|
||||
* valid. It hasn't got any checksums filled in, for one, and lots of fields
|
||||
* are just zeroed.) */
|
||||
void
|
||||
flow_compose(struct ofpbuf *b, const struct flow *flow)
|
||||
{
|
||||
eth_compose(b, flow->dl_dst, flow->dl_src, ntohs(flow->dl_type), 0);
|
||||
if (flow->dl_type == htons(FLOW_DL_TYPE_NONE)) {
|
||||
struct eth_header *eth = b->l2;
|
||||
eth->eth_type = htons(b->size);
|
||||
return;
|
||||
}
|
||||
|
||||
if (flow->vlan_tci & htons(VLAN_CFI)) {
|
||||
eth_push_vlan(b, flow->vlan_tci & ~htons(VLAN_CFI));
|
||||
}
|
||||
|
||||
if (flow->dl_type == htons(ETH_TYPE_IP)) {
|
||||
struct ip_header *ip;
|
||||
|
||||
b->l3 = ip = ofpbuf_put_zeros(b, sizeof *ip);
|
||||
ip->ip_ihl_ver = IP_IHL_VER(5, 4);
|
||||
ip->ip_tos = flow->nw_tos;
|
||||
ip->ip_proto = flow->nw_proto;
|
||||
ip->ip_src = flow->nw_src;
|
||||
ip->ip_dst = flow->nw_dst;
|
||||
|
||||
if (flow->nw_proto == IPPROTO_TCP) {
|
||||
struct tcp_header *tcp;
|
||||
|
||||
b->l4 = tcp = ofpbuf_put_zeros(b, sizeof *tcp);
|
||||
tcp->tcp_src = flow->tp_src;
|
||||
tcp->tcp_dst = flow->tp_dst;
|
||||
} else if (flow->nw_proto == IPPROTO_UDP) {
|
||||
struct udp_header *udp;
|
||||
|
||||
b->l4 = udp = ofpbuf_put_zeros(b, sizeof *udp);
|
||||
udp->udp_src = flow->tp_src;
|
||||
udp->udp_dst = flow->tp_dst;
|
||||
} else if (flow->nw_proto == IPPROTO_ICMP) {
|
||||
struct icmp_header *icmp;
|
||||
|
||||
b->l4 = icmp = ofpbuf_put_zeros(b, sizeof *icmp);
|
||||
icmp->icmp_type = ntohs(flow->tp_src);
|
||||
icmp->icmp_code = ntohs(flow->tp_dst);
|
||||
}
|
||||
} else if (flow->dl_type == htons(ETH_TYPE_IPV6)) {
|
||||
/* XXX */
|
||||
} else if (flow->dl_type == htons(ETH_TYPE_ARP)) {
|
||||
struct arp_eth_header *arp;
|
||||
|
||||
b->l3 = arp = ofpbuf_put_zeros(b, sizeof *arp);
|
||||
arp->ar_hrd = htons(1);
|
||||
arp->ar_pro = htons(ETH_TYPE_IP);
|
||||
arp->ar_hln = ETH_ADDR_LEN;
|
||||
arp->ar_pln = 4;
|
||||
arp->ar_op = htons(flow->nw_proto);
|
||||
|
||||
if (flow->nw_proto == ARP_OP_REQUEST ||
|
||||
flow->nw_proto == ARP_OP_REPLY) {
|
||||
arp->ar_spa = flow->nw_src;
|
||||
arp->ar_tpa = flow->nw_dst;
|
||||
memcpy(arp->ar_sha, flow->arp_sha, ETH_ADDR_LEN);
|
||||
memcpy(arp->ar_tha, flow->arp_tha, ETH_ADDR_LEN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -89,6 +89,8 @@ static inline int flow_compare(const struct flow *, const struct flow *);
|
||||
static inline bool flow_equal(const struct flow *, const struct flow *);
|
||||
static inline size_t flow_hash(const struct flow *, uint32_t basis);
|
||||
|
||||
void flow_compose(struct ofpbuf *, const struct flow *);
|
||||
|
||||
static inline int
|
||||
flow_compare(const struct flow *a, const struct flow *b)
|
||||
{
|
||||
|
@@ -4099,8 +4099,8 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, const char *args_,
|
||||
arg1 = strtok_r(NULL, " ", &save_ptr);
|
||||
arg2 = strtok_r(NULL, " ", &save_ptr);
|
||||
arg3 = strtok_r(NULL, "", &save_ptr); /* Get entire rest of line. */
|
||||
if (dpname && arg1 && !arg2 && !arg3) {
|
||||
/* ofproto/trace dpname flow */
|
||||
if (dpname && arg1 && (!arg2 || !strcmp(arg2, "-generate")) && !arg3) {
|
||||
/* ofproto/trace dpname flow [-generate] */
|
||||
int error;
|
||||
|
||||
/* Convert string to datapath key. */
|
||||
@@ -4117,6 +4117,12 @@ ofproto_unixctl_trace(struct unixctl_conn *conn, const char *args_,
|
||||
unixctl_command_reply(conn, 501, "Invalid flow");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Generate a packet, if requested. */
|
||||
if (arg2) {
|
||||
packet = ofpbuf_new(0);
|
||||
flow_compose(packet, &flow);
|
||||
}
|
||||
} else if (dpname && arg1 && arg2 && arg3) {
|
||||
/* ofproto/trace dpname tun_id in_port packet */
|
||||
uint16_t in_port;
|
||||
|
@@ -7,12 +7,12 @@ Lists the names of the running ofproto instances. These are the names
|
||||
that may be used on \fBofproto/trace\fR.
|
||||
.
|
||||
.IP "\fBofproto/trace \fIswitch tun_id in_port packet\fR"
|
||||
Traces the path of an imaginary packet through \fIswitch\fR. The
|
||||
arguments are:
|
||||
.IQ "\fBofproto/trace \fIswitch odp_flow \fB\-generate\fR"
|
||||
Traces the path of an imaginary packet through \fIswitch\fR. Both
|
||||
forms require \fIswitch\fR, the switch on which the packet arrived
|
||||
(one of those listed by \fBofproto/list\fR). The first form specifies
|
||||
a packet's contents explicitly:
|
||||
.RS
|
||||
.IP "\fIswitch\fR"
|
||||
The switch on which the packet arrived (one of those listed by
|
||||
\fBofproto/list\fR).
|
||||
.IP "\fItun_id\fR"
|
||||
The tunnel ID on which the packet arrived. Use
|
||||
\fB0\fR if the packet did not arrive through a tunnel.
|
||||
@@ -27,9 +27,18 @@ by hand, so the \fBovs\-pcap\fR(1) and \fBovs\-tcpundump\fR(1)
|
||||
utilities provide easier ways.
|
||||
.RE
|
||||
.IP
|
||||
The second form specifies the packet's contents implicitly:
|
||||
.RS
|
||||
.IP "\fIodp_flow\fR"
|
||||
A flow in the form printed by \fBovs\-dpctl\fR(8)'s \fBdump\-flows\fR
|
||||
command. This is not an OpenFlow flow: besides other differences, it
|
||||
never contains wildcards. \fB\*(PN\fR generates an arbitrary packet
|
||||
that has the specified \fIodp_flow\fR.
|
||||
.RE
|
||||
.IP
|
||||
\fB\*(PN\fR will respond with extensive information on how the packet
|
||||
would be handled if it were to be received. The packet will not
|
||||
actually be sent.
|
||||
actually be sent, but side effects such as MAC learning will occur.
|
||||
.
|
||||
.IP "\fBofproto/trace \fIswitch odp_flow\fR"
|
||||
Traces the path of a packet in an imaginary flow through
|
||||
@@ -46,7 +55,8 @@ never contains wildcards.
|
||||
.IP
|
||||
\fB\*(PN\fR will respond with extensive information on how a packet
|
||||
in \fIodp_flow\fR would be handled if it were received by
|
||||
\fIswitch\fR. No packet will actually be sent.
|
||||
\fIswitch\fR. No packet will actually be sent. Some side effects may
|
||||
occur, but MAC learning in particular will not.
|
||||
.IP
|
||||
This form of \fBofproto/trace\fR cannot determine the complete set of
|
||||
datapath actions in some corner cases. If the results say that this
|
||||
|
Reference in New Issue
Block a user