Signed-off-by: Jarno Rajahalme <jarno.rajaha...@nsn.com> --- lib/packets.h | 10 +++++- ofproto/in-band.c | 29 ++++++++++-------- ofproto/ofproto-dpif.c | 80 ++++++++++++++++++++++++++++++------------------ 3 files changed, 76 insertions(+), 43 deletions(-)
diff --git a/lib/packets.h b/lib/packets.h index 0f97fe6..428d702 100644 --- a/lib/packets.h +++ b/lib/packets.h @@ -27,8 +27,8 @@ #include "openvswitch/types.h" #include "random.h" #include "util.h" +#include "ofpbuf.h" -struct ofpbuf; struct ds; bool dpid_from_string(const char *s, uint64_t *dpidp); @@ -586,4 +586,12 @@ void packet_set_udp_port(struct ofpbuf *, ovs_be16 src, ovs_be16 dst); uint8_t packet_get_tcp_flags(const struct ofpbuf *, const struct flow *); void packet_format_tcp_flags(struct ds *, uint8_t); +static inline void packet_check_pointers(struct ofpbuf *packet) { + /* Need to set packet pointers l2_5/l3/l4/l7 ? */ + if (packet->l3 == NULL) { + struct flow flow; + flow_extract_l2_onwards(packet, &flow); + } +} + #endif /* packets.h */ diff --git a/ofproto/in-band.c b/ofproto/in-band.c index 3b98005..ae43e12 100644 --- a/ofproto/in-band.c +++ b/ofproto/in-band.c @@ -233,20 +233,23 @@ in_band_msg_in_hook(struct in_band *in_band, const struct flow *flow, if (flow->dl_type == htons(ETH_TYPE_IP) && flow->nw_proto == IPPROTO_UDP && flow->tp_src == htons(DHCP_SERVER_PORT) - && flow->tp_dst == htons(DHCP_CLIENT_PORT) - && packet->l7) { - struct dhcp_header *dhcp; - - dhcp = ofpbuf_at(packet, (char *)packet->l7 - (char *)packet->data, - sizeof *dhcp); - if (!dhcp) { - return false; - } + && flow->tp_dst == htons(DHCP_CLIENT_PORT)) { + /* Deferred setting of packet layer pointers? */ + packet_check_pointers(CONST_CAST(struct ofpbuf *, packet)); + if (packet->l7) { + struct dhcp_header *dhcp; + + dhcp = ofpbuf_at(packet, (char *)packet->l7 - (char *)packet->data, + sizeof *dhcp); + if (!dhcp) { + return false; + } - refresh_local(in_band); - if (!eth_addr_is_zero(in_band->local_mac) - && eth_addr_equals(dhcp->chaddr, in_band->local_mac)) { - return true; + refresh_local(in_band); + if (!eth_addr_is_zero(in_band->local_mac) + && eth_addr_equals(dhcp->chaddr, in_band->local_mac)) { + return true; + } } } diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 594f3f3..d0459e5 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -3321,17 +3321,23 @@ process_special(struct ofproto_dpif *ofproto, const struct flow *flow, if (ofport->cfm && cfm_should_process_flow(ofport->cfm, flow)) { if (packet) { + /* Deferred setting of packet layer pointers? */ + packet_check_pointers(CONST_CAST(struct ofpbuf *, packet)); cfm_process_heartbeat(ofport->cfm, packet); } return SLOW_CFM; } else if (ofport->bundle && ofport->bundle->lacp && flow->dl_type == htons(ETH_TYPE_LACP)) { if (packet) { + /* Deferred setting of packet layer pointers? */ + packet_check_pointers(CONST_CAST(struct ofpbuf *, packet)); lacp_process_packet(ofport->bundle->lacp, ofport, packet); } return SLOW_LACP; } else if (ofproto->stp && stp_should_process_flow(flow)) { if (packet) { + /* Deferred setting of packet layer pointers? */ + packet_check_pointers(CONST_CAST(struct ofpbuf *, packet)); stp_process_packet(ofport, packet); } return SLOW_STP; @@ -3521,6 +3527,8 @@ handle_flow_miss_with_facet(struct flow_miss *miss, struct facet *facet, packet_stats_extract(packet, now, &stats); if (facet->has_fin_timeout || ofproto->netflow) { + packet_check_pointers(packet); /* Deferred setting of packet layer + * pointers? */ stats.tcp_flags = packet_get_tcp_flags(packet, &facet->flow); } subfacet_update_stats(subfacet, &stats); @@ -3642,7 +3650,7 @@ drop_key_clear(struct dpif_backer *backer) } } -/* Given a datpath, packet, and flow metadata ('backer', 'packet', and 'key' +/* Given a datapath, packet, and flow metadata ('backer', 'packet', and 'key' * respectively), populates 'flow' with the result of odp_flow_key_to_flow(). * Optionally, if nonnull, populates 'fitnessp' with the fitness of 'flow' as * returned by odp_flow_key_to_flow(). Also, optionally populates 'ofproto' @@ -3792,7 +3800,6 @@ do_handle_upcalls(struct dpif_backer *backer, struct dpif_upcall *upcalls, struct flow_miss *existing_miss; struct ofproto_dpif *ofproto; uint32_t odp_in_port; - struct flow flow; uint32_t hash; int error; @@ -3810,38 +3817,50 @@ do_handle_upcalls(struct dpif_backer *backer, struct dpif_upcall *upcalls, } error = ofproto_receive(backer, upcall->packet, upcall->key, - upcall->key_len, &flow, &miss->key_fitness, + upcall->key_len, &miss->flow, &miss->key_fitness, &ofproto, &odp_in_port, &miss->initial_tci); - if (error == ENODEV) { - struct drop_key *drop_key; - - /* Received packet on port for which we couldn't associate - * an ofproto. This can happen if a port is removed while - * traffic is being received. Print a rate-limited message - * in case it happens frequently. Install a drop flow so - * that future packets of the flow are inexpensively dropped - * in the kernel. */ - VLOG_INFO_RL(&rl, "received packet on unassociated port %"PRIu32, - flow.in_port); - - drop_key = drop_key_lookup(backer, upcall->key, upcall->key_len); - if (!drop_key) { - drop_key = xmalloc(sizeof *drop_key); - drop_key->key = xmemdup(upcall->key, upcall->key_len); - drop_key->key_len = upcall->key_len; - - hmap_insert(&backer->drop_keys, &drop_key->hmap_node, - hash_bytes(drop_key->key, drop_key->key_len, 0)); - dpif_flow_put(backer->dpif, DPIF_FP_CREATE | DPIF_FP_MODIFY, - drop_key->key, drop_key->key_len, NULL, 0, NULL); + if (error) { + if (error == ENODEV) { + struct drop_key *drop_key; + + /* Received packet on port for which we couldn't associate + * an ofproto. This can happen if a port is removed while + * traffic is being received. Print a rate-limited message + * in case it happens frequently. Install a drop flow so + * that future packets of the flow are inexpensively dropped + * in the kernel. */ + VLOG_INFO_RL(&rl, "received packet on unassociated port %"PRIu32, + miss->flow.in_port); + + drop_key = drop_key_lookup(backer, upcall->key, upcall->key_len); + if (!drop_key) { + drop_key = xmalloc(sizeof *drop_key); + drop_key->key = xmemdup(upcall->key, upcall->key_len); + drop_key->key_len = upcall->key_len; + + hmap_insert(&backer->drop_keys, &drop_key->hmap_node, + hash_bytes(drop_key->key, drop_key->key_len, 0)); + dpif_flow_put(backer->dpif, DPIF_FP_CREATE | DPIF_FP_MODIFY, + drop_key->key, drop_key->key_len, NULL, 0, NULL); + } } continue; } - if (error) { - continue; + + if (miss->key_fitness == ODP_FIT_PERFECT) { + /* We have a perfect key fitness, keep the flow. + * This is safe because MISS_UPCALLs never have the + * packet modified by any actions before being passed to us. */ + + /* Init l2 layer pointer and leave the rest for later */ + upcall->packet->l2 = upcall->packet->data; + } else { + /* The packet may have been modified since the key extraction, + * or the kernel provided key may otherwise be insufficient. + * Do full flow key extraction, but keep the metadata. + */ + flow_extract_l2_onwards(upcall->packet, &miss->flow); } - flow_extract(upcall->packet, flow.skb_priority, flow.skb_mark, - &flow.tunnel, flow.in_port, &miss->flow); /* Add other packets to a to-do list. */ hash = flow_hash(&miss->flow, 0); @@ -5935,6 +5954,9 @@ execute_controller_action(struct action_xlate_ctx *ctx, int len, return; } + /* Deferred setting of packet layer pointers? */ + packet_check_pointers(CONST_CAST(struct ofpbuf *, ctx->packet)); + packet = ofpbuf_clone(ctx->packet); if (packet->l2 && packet->l3) { -- 1.7.10.4 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev