I like this, some comments below, otherwise: Acked-by: Jarno Rajahalme <jrajaha...@nicira.com>
On Feb 26, 2014, at 6:22 PM, Andy Zhou <az...@nicira.com> wrote: > Change the flow_extract() API to accept struct pkt_metadta, > instead of individual metadata fields. It will make the API more > logical and easier to maintain when we need to expand metadata > down the road. > > Signed-off-by: Andy Zhou <az...@nicira.com> > --- > lib/dpif-netdev.c | 6 ++---- > lib/flow.c | 20 ++++++++------------ > lib/flow.h | 4 ++-- > lib/learning-switch.c | 4 +++- > lib/ofp-print.c | 4 +++- > lib/packets.c | 28 ++++++++++++++++++++++++++++ > lib/packets.h | 7 +++++++ > ofproto/ofproto-dpif-upcall.c | 5 +++-- > ofproto/ofproto-dpif-xlate.c | 5 ++++- > ofproto/ofproto-dpif.c | 7 +++++-- > ofproto/ofproto.c | 8 ++++++-- > tests/test-flows.c | 4 +++- > utilities/ovs-ofctl.c | 6 ++++-- > 13 files changed, 78 insertions(+), 30 deletions(-) > > diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c > index c4ba646..6b07817 100644 > --- a/lib/dpif-netdev.c > +++ b/lib/dpif-netdev.c > @@ -1419,8 +1419,7 @@ dpif_netdev_execute(struct dpif *dpif, struct > dpif_execute *execute) > } > > /* Extract flow key. */ > - flow_extract(execute->packet, md->skb_priority, md->pkt_mark, > &md->tunnel, > - (union flow_in_port *)&md->in_port, &key); > + flow_extract(execute->packet, md, &key); > > ovs_rwlock_rdlock(&dp->port_rwlock); > dp_netdev_execute_actions(dp, &key, execute->packet, md, execute->actions, > @@ -1693,8 +1692,7 @@ dp_netdev_port_input(struct dp_netdev *dp, struct > ofpbuf *packet, > if (packet->size < ETH_HEADER_LEN) { > return; > } > - flow_extract(packet, md->skb_priority, md->pkt_mark, &md->tunnel, > - (union flow_in_port *)&md->in_port, &key); > + flow_extract(packet, md, &key); > netdev_flow = dp_netdev_lookup_flow(dp, &key); > if (netdev_flow) { > struct dp_netdev_actions *actions; > diff --git a/lib/flow.c b/lib/flow.c > index e7fe4d3..3fa61a8 100644 > --- a/lib/flow.c > +++ b/lib/flow.c > @@ -35,6 +35,7 @@ > #include "ofpbuf.h" > #include "openflow/openflow.h" > #include "packets.h" > +#include "odp-util.h" > #include "random.h" > #include "unaligned.h" > > @@ -361,8 +362,7 @@ invalid: > > } > > -/* Initializes 'flow' members from 'packet', 'skb_priority', 'tnl', and > - * 'in_port'. > +/* Initializes 'flow' members from 'packet' and 'md' > * > * Initializes 'packet' header pointers as follows: > * > @@ -381,8 +381,7 @@ invalid: > * present and has a correct length, and otherwise NULL. > */ > void > -flow_extract(struct ofpbuf *packet, uint32_t skb_priority, uint32_t pkt_mark, > - const struct flow_tnl *tnl, const union flow_in_port *in_port, > +flow_extract(struct ofpbuf *packet, const struct pkt_metadata *md, > struct flow *flow) > { > struct ofpbuf b = *packet; > @@ -392,15 +391,12 @@ flow_extract(struct ofpbuf *packet, uint32_t > skb_priority, uint32_t pkt_mark, > > memset(flow, 0, sizeof *flow); > > - if (tnl) { > - ovs_assert(tnl != &flow->tunnel); > - flow->tunnel = *tnl; > + flow->tunnel = md->tunnel; > + if (md->in_port != ODPP_NONE) { > + flow->in_port.odp_port = md->in_port; > } > - if (in_port) { > - flow->in_port = *in_port; > - } > - flow->skb_priority = skb_priority; > - flow->pkt_mark = pkt_mark; > + flow->skb_priority = md->skb_priority; > + flow->pkt_mark = md->pkt_mark; > It seems it could be beneficial to accept the ‘md’ argument as NULL and leave the metadata zeroed in that case. There are a number of callers that would benefit from this (see below). > packet->l2 = b.data; > packet->l2_5 = NULL; > diff --git a/lib/flow.h b/lib/flow.h > index 3109a84..1e8d137 100644 > --- a/lib/flow.h > +++ b/lib/flow.h > @@ -32,6 +32,7 @@ struct ds; > struct flow_wildcards; > struct minimask; > struct ofpbuf; > +struct pkt_metadata; > > /* This sequence number should be incremented whenever anything involving > flows > * or the wildcarding of flows changes. This will cause build assertion > @@ -173,8 +174,7 @@ struct flow_metadata { > ofp_port_t in_port; /* OpenFlow port or zero. */ > }; > > -void flow_extract(struct ofpbuf *, uint32_t priority, uint32_t mark, > - const struct flow_tnl *, const union flow_in_port *in_port, > +void flow_extract(struct ofpbuf *, const struct pkt_metadata *md, > struct flow *); > > void flow_zero_wildcards(struct flow *, const struct flow_wildcards *); > diff --git a/lib/learning-switch.c b/lib/learning-switch.c > index 8efbce1..ef2976f 100644 > --- a/lib/learning-switch.c > +++ b/lib/learning-switch.c > @@ -547,6 +547,7 @@ process_packet_in(struct lswitch *sw, const struct > ofp_header *oh) > struct ofputil_packet_in pi; > uint32_t queue_id; > ofp_port_t out_port; > + struct pkt_metadata md; > > uint64_t ofpacts_stub[64 / 8]; > struct ofpbuf ofpacts; > @@ -575,7 +576,8 @@ process_packet_in(struct lswitch *sw, const struct > ofp_header *oh) > /* Extract flow data from 'opi' into 'flow'. */ > ofpbuf_use_const(&pkt, pi.packet, pi.packet_len); > in_port_.ofp_port = pi.fmd.in_port; > - flow_extract(&pkt, 0, 0, NULL, &in_port_, &flow); > + pkt_metadata_init(&md, &in_port_); > + flow_extract(&pkt, &md, &flow); Use NULL ‘md’ here, and set the port after extract: flow.in_port_.ofp_port = pi.fmd.in_port; A rationale for this would be that pkt_metadata does not really exist in this case, as even the port number is an OpenFlow port number, rather than a datapath port number. > flow.tunnel.tun_id = pi.fmd.tun_id; > > /* Choose output port. */ > diff --git a/lib/ofp-print.c b/lib/ofp-print.c > index 4c89b36..06e64f6 100644 > --- a/lib/ofp-print.c > +++ b/lib/ofp-print.c > @@ -46,6 +46,7 @@ > #include "packets.h" > #include "type-props.h" > #include "unaligned.h" > +#include "odp-util.h" > #include "util.h" > > static void ofp_print_queue_name(struct ds *string, uint32_t port); > @@ -58,11 +59,12 @@ char * > ofp_packet_to_string(const void *data, size_t len) > { > struct ds ds = DS_EMPTY_INITIALIZER; > + const struct pkt_metadata md = PKT_METADATA_INITIALIZER(ODPP_NONE); > struct ofpbuf buf; > struct flow flow; > > ofpbuf_use_const(&buf, data, len); > - flow_extract(&buf, 0, 0, NULL, NULL, &flow); > + flow_extract(&buf, &md, &flow); Use NULL ‘md’ argument instead. > flow_format(&ds, &flow); > > if (buf.l7) { > diff --git a/lib/packets.c b/lib/packets.c > index 7238f42..0286954 100644 > --- a/lib/packets.c > +++ b/lib/packets.c > @@ -29,6 +29,7 @@ > #include "dynamic-string.h" > #include "ofpbuf.h" > #include "ovs-thread.h" > +#include "odp-util.h" > #include "unaligned.h" > > const struct in6_addr in6addr_exact = IN6ADDR_EXACT_INIT; > @@ -991,3 +992,30 @@ packet_format_tcp_flags(struct ds *s, uint16_t tcp_flags) > ds_put_cstr(s, "[800]"); > } > } > + > +void pkt_metadata_init(struct pkt_metadata *md, > + const union flow_in_port* in_port) > +{ > + pkt_metadata_init_full(md, NULL, 0, 0, in_port); > +} This might not be needed. > + > +void pkt_metadata_init_full(struct pkt_metadata *md, const struct flow_tnl > *tnl, > + const uint32_t skb_priority, > + const uint32_t pkt_mark, > + const union flow_in_port *in_port) > +{ > + Extra blank line here. > + tnl ? memcpy(&md->tunnel, tnl, sizeof(md->tunnel)) > + : memset(&md->tunnel, 0, sizeof(md->tunnel)); > + > + md->skb_priority = skb_priority; > + md->pkt_mark = pkt_mark; > + md->in_port = in_port ? in_port->odp_port : ODPP_NONE; > +} This would be better named “pot_metadata_init()”, once the previous function is removed. > + > +void pkt_metadata_from_flow(struct pkt_metadata *md, const struct flow *flow) > +{ > + Extra blanck line here. > + pkt_metadata_init_full(md, &flow->tunnel, flow->skb_priority, > + flow->pkt_mark, &flow->in_port); > +} > diff --git a/lib/packets.h b/lib/packets.h > index 1855a1c..5e1d52d 100644 > --- a/lib/packets.h > +++ b/lib/packets.h > @@ -42,6 +42,13 @@ struct pkt_metadata { > #define PKT_METADATA_INITIALIZER(PORT) \ > (struct pkt_metadata){ { 0, 0, 0, 0, 0, 0}, 0, 0, (PORT) } > > +void pkt_metadata_init(struct pkt_metadata *md, const union flow_in_port > *in_port); > +void pkt_metadata_init_full(struct pkt_metadata *md, const struct flow_tnl > *tnl, > + const uint32_t skb_priority, > + const uint32_t pkt_mark, > + const union flow_in_port *in_port); > +void pkt_metadata_from_flow(struct pkt_metadata *md, const struct flow > *flow); > + > bool dpid_from_string(const char *s, uint64_t *dpidp); > > #define ETH_ADDR_LEN 6 > diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c > index e4f81a1..6cc0b67 100644 > --- a/ofproto/ofproto-dpif-upcall.c > +++ b/ofproto/ofproto-dpif-upcall.c > @@ -983,9 +983,10 @@ handle_upcalls(struct handler *handler, struct list > *upcalls) > type = classify_upcall(upcall); > if (type == MISS_UPCALL) { > uint32_t hash; > + struct pkt_metadata md; > > - flow_extract(packet, flow.skb_priority, flow.pkt_mark, > - &flow.tunnel, &flow.in_port, &miss->flow); > + pkt_metadata_from_flow(&md, &flow); > + flow_extract(packet, &md, &miss->flow); > > hash = flow_hash(&miss->flow, 0); > existing_miss = flow_miss_find(&misses, ofproto, &miss->flow, > diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c > index 89d92af..0955d64 100644 > --- a/ofproto/ofproto-dpif-xlate.c > +++ b/ofproto/ofproto-dpif-xlate.c > @@ -3184,12 +3184,15 @@ xlate_send_packet(const struct ofport_dpif *ofport, > struct ofpbuf *packet) > struct xport *xport; > struct ofpact_output output; > struct flow flow; > + struct pkt_metadata md; > union flow_in_port in_port_; > > ofpact_init(&output.ofpact, OFPACT_OUTPUT, sizeof output); > /* Use OFPP_NONE as the in_port to avoid special packet processing. */ > in_port_.ofp_port = OFPP_NONE; > - flow_extract(packet, 0, 0, NULL, &in_port_, &flow); > + > + pkt_metadata_init(&md, &in_port_); > + flow_extract(packet, &md, &flow); > Use NULL ‘md’ and set the port to OFPP_NONE after extract. > ovs_rwlock_rdlock(&xlate_rwlock); > xport = xport_lookup(ofport); > diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c > index c597114..6c48c18 100644 > --- a/ofproto/ofproto-dpif.c > +++ b/ofproto/ofproto-dpif.c > @@ -3784,11 +3784,14 @@ parse_flow_and_packet(int argc, const char *argv[], > flow_compose(packet, flow); > } else { > union flow_in_port in_port = flow->in_port; > + struct pkt_metadata md; > > /* Use the metadata from the flow and the packet argument > * to reconstruct the flow. */ > - flow_extract(packet, flow->skb_priority, flow->pkt_mark, NULL, > - &in_port, flow); > + pkt_metadata_init_full(&md, NULL, flow->skb_priority, > + flow->pkt_mark, &in_port); > + Seems you could use the pkt_metadata_from_flow() here? I guess even the flow->tunnel is zeroes here? > + flow_extract(packet, &md, flow); > } > } > > diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c > index 7117e1f..e400b32 100644 > --- a/ofproto/ofproto.c > +++ b/ofproto/ofproto.c > @@ -2715,9 +2715,11 @@ run_rule_executes(struct ofproto *ofproto) > LIST_FOR_EACH_SAFE (e, next, list_node, &executes) { > union flow_in_port in_port_; > struct flow flow; > + struct pkt_metadata md; > > in_port_.ofp_port = e->in_port; > - flow_extract(e->packet, 0, 0, NULL, &in_port_, &flow); > + pkt_metadata_init(&md, &in_port_); > + flow_extract(e->packet, &md, &flow); Use NULL ‘md’ and set the port number here: flow.in_port_.ofp_port = e->in_port; > ofproto->ofproto_class->rule_execute(e->rule, &flow, e->packet); > > rule_execute_destroy(e); > @@ -2928,6 +2930,7 @@ handle_packet_out(struct ofconn *ofconn, const struct > ofp_header *oh) > struct flow flow; > union flow_in_port in_port_; > enum ofperr error; > + struct pkt_metadata md; > > COVERAGE_INC(ofproto_packet_out); > > @@ -2961,7 +2964,8 @@ handle_packet_out(struct ofconn *ofconn, const struct > ofp_header *oh) > > /* Verify actions against packet, then send packet if successful. */ > in_port_.ofp_port = po.in_port; > - flow_extract(payload, 0, 0, NULL, &in_port_, &flow); > + pkt_metadata_init(&md, &in_port_); > + flow_extract(payload, &md, &flow); Use NULL ‘md’ and set the port after. > error = ofproto_check_ofpacts(p, po.ofpacts, po.ofpacts_len); > if (!error) { > error = p->ofproto_class->packet_out(p, payload, &flow, > diff --git a/tests/test-flows.c b/tests/test-flows.c > index 2910035..7907523 100644 > --- a/tests/test-flows.c > +++ b/tests/test-flows.c > @@ -58,6 +58,7 @@ main(int argc OVS_UNUSED, char *argv[]) > struct ofp10_match extracted_match; > struct match match; > struct flow flow; > + struct pkt_metadata md; > union flow_in_port in_port_; > n++; > > @@ -69,7 +70,8 @@ main(int argc OVS_UNUSED, char *argv[]) > } > > in_port_.ofp_port = u16_to_ofp(1); > - flow_extract(packet, 0, 0, NULL, &in_port_, &flow); > + pkt_metadata_init(&md, &in_port_); > + flow_extract(packet, &md, &flow); Use NULL ‘md’ and set the port after. > match_wc_init(&match, &flow); > ofputil_match_to_ofp10_match(&match, &extracted_match); > > diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c > index 4ab9ca4..e62e646 100644 > --- a/utilities/ovs-ofctl.c > +++ b/utilities/ovs-ofctl.c > @@ -1864,12 +1864,13 @@ ofctl_ofp_parse_pcap(int argc OVS_UNUSED, char > *argv[]) > struct ofpbuf *packet; > long long int when; > struct flow flow; > + const struct pkt_metadata md = PKT_METADATA_INITIALIZER(ODPP_NONE); > > error = ovs_pcap_read(file, &packet, &when); > if (error) { > break; > } > - flow_extract(packet, 0, 0, NULL, NULL, &flow); > + flow_extract(packet, &md, &flow); Use NULL ‘md’ instead. > if (flow.dl_type == htons(ETH_TYPE_IP) > && flow.nw_proto == IPPROTO_TCP > && (is_openflow_port(flow.tp_src, argv + 2) || > @@ -3208,6 +3209,7 @@ ofctl_parse_pcap(int argc OVS_UNUSED, char *argv[]) > for (;;) { > struct ofpbuf *packet; > struct flow flow; > + const struct pkt_metadata md = PKT_METADATA_INITIALIZER(ODPP_NONE); > int error; > > error = ovs_pcap_read(pcap, &packet, NULL); > @@ -3217,7 +3219,7 @@ ofctl_parse_pcap(int argc OVS_UNUSED, char *argv[]) > ovs_fatal(error, "%s: read failed", argv[1]); > } > > - flow_extract(packet, 0, 0, NULL, NULL, &flow); > + flow_extract(packet, &md, &flow); Use NULL ‘md’ instead. > flow_print(stdout, &flow); > putchar('\n'); > ofpbuf_delete(packet); > -- > 1.7.9.5 > > _______________________________________________ > dev mailing list > dev@openvswitch.org > http://openvswitch.org/mailman/listinfo/dev _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev