[ovs-dev] [learning v2 11/19] ofproto-dpif: Add -packet option to ofproto/trace command.
Ben Pfaff
blp at nicira.com
Fri Aug 19 22:28:26 UTC 2011
---
lib/flow.c | 71 +++++++++++++++++++++++++++++++++++++++++++
lib/flow.h | 2 +
ofproto/ofproto-dpif.c | 10 +++++-
ofproto/ofproto-unixctl.man | 24 ++++++++++----
4 files changed, 98 insertions(+), 9 deletions(-)
diff --git a/lib/flow.c b/lib/flow.c
index 460771c..2599de6 100644
--- a/lib/flow.c
+++ b/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_set_vlan_tci(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);
+ }
+ }
+}
diff --git a/lib/flow.h b/lib/flow.h
index d049e7e..1b3ee18 100644
--- a/lib/flow.h
+++ b/lib/flow.h
@@ -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)
{
diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c
index 414c82b..3130da4 100644
--- a/ofproto/ofproto-dpif.c
+++ b/ofproto/ofproto-dpif.c
@@ -4074,8 +4074,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, "-packet")) && !arg3) {
+ /* ofproto/trace dpname flow [-packet] */
int error;
/* Convert string to ODP key. */
@@ -4092,6 +4092,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;
diff --git a/ofproto/ofproto-unixctl.man b/ofproto/ofproto-unixctl.man
index 06db7e0..3da4227 100644
--- a/ofproto/ofproto-unixctl.man
+++ b/ofproto/ofproto-unixctl.man
@@ -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\-packet\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
--
1.7.4.4
More information about the dev
mailing list