2
0
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:
Ben Pfaff
2011-09-08 14:32:13 -07:00
parent 6a885fd058
commit 8b3b8dd1a5
4 changed files with 98 additions and 9 deletions

View File

@@ -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);
}
}
}

View File

@@ -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)
{

View File

@@ -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;

View File

@@ -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