Skip to content

Commit

Permalink
ofproto-dpif: Add -generate option to ofproto/trace command.
Browse files Browse the repository at this point in the history
  • Loading branch information
blp committed Sep 13, 2011
1 parent 6a885fd commit 8b3b8dd
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 9 deletions.
71 changes: 71 additions & 0 deletions lib/flow.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
2 changes: 2 additions & 0 deletions lib/flow.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
10 changes: 8 additions & 2 deletions ofproto/ofproto-dpif.c
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand All @@ -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;
Expand Down
24 changes: 17 additions & 7 deletions ofproto/ofproto-unixctl.man
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand All @@ -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
Expand Down

0 comments on commit 8b3b8dd

Please sign in to comment.