From: Justin Pettit Date: Tue, 18 Jun 2013 01:07:33 +0000 (-0700) Subject: ofproto-dpif: Don't wildcard fields used in special processing. X-Git-Tag: sliver-openvswitch-1.10.90-3~6^2~101 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=642dc74ddb13bf0a0948c3ca0013bd62f8074a9f;hp=db7d4e469903adf1cbf05c9cd70b9eb77946c202;p=sliver-openvswitch.git ofproto-dpif: Don't wildcard fields used in special processing. A number of fields are looked at when determining whether special processing (slow-path) is needed. This commit removes wildcarding when they were consulted. Reported-by: Ethan Jackson Reported-by: Paul Ingram Signed-off-by: Justin Pettit --- diff --git a/lib/bfd.c b/lib/bfd.c index 9f671f2e8..ddf8c4cba 100644 --- a/lib/bfd.c +++ b/lib/bfd.c @@ -414,8 +414,11 @@ bfd_put_packet(struct bfd *bfd, struct ofpbuf *p, } bool -bfd_should_process_flow(const struct flow *flow) +bfd_should_process_flow(const struct flow *flow, struct flow_wildcards *wc) { + memset(&wc->masks.dl_type, 0xff, sizeof wc->masks.dl_type); + memset(&wc->masks.nw_proto, 0xff, sizeof wc->masks.nw_proto); + memset(&wc->masks.tp_dst, 0xff, sizeof wc->masks.tp_dst); return (flow->dl_type == htons(ETH_TYPE_IP) && flow->nw_proto == IPPROTO_UDP && flow->tp_dst == htons(3784)); diff --git a/lib/bfd.h b/lib/bfd.h index 21203b389..61f9945f9 100644 --- a/lib/bfd.h +++ b/lib/bfd.h @@ -23,6 +23,7 @@ struct bfd; struct flow; +struct flow_wildcards; struct ofpbuf; struct smap; @@ -33,7 +34,7 @@ bool bfd_should_send_packet(const struct bfd *); void bfd_put_packet(struct bfd *bfd, struct ofpbuf *packet, uint8_t eth_src[6]); -bool bfd_should_process_flow(const struct flow *); +bool bfd_should_process_flow(const struct flow *, struct flow_wildcards *); void bfd_process_packet(struct bfd *, const struct flow *, const struct ofpbuf *); diff --git a/lib/cfm.c b/lib/cfm.c index 64ad18cfa..67c2002f6 100644 --- a/lib/cfm.c +++ b/lib/cfm.c @@ -577,10 +577,17 @@ cfm_set_netdev(struct cfm *cfm, const struct netdev *netdev) } } -/* Returns true if 'cfm' should process packets from 'flow'. */ +/* Returns true if 'cfm' should process packets from 'flow'. Sets + * fields in 'wc' that were used to make the determination. */ bool -cfm_should_process_flow(const struct cfm *cfm, const struct flow *flow) +cfm_should_process_flow(const struct cfm *cfm, const struct flow *flow, + struct flow_wildcards *wc) { + memset(&wc->masks.dl_dst, 0xff, sizeof wc->masks.dl_dst); + memset(&wc->masks.dl_type, 0xff, sizeof wc->masks.dl_type); + if (cfm->check_tnl_key) { + memset(&wc->masks.tunnel.tun_id, 0xff, sizeof wc->masks.tunnel.tun_id); + } return (ntohs(flow->dl_type) == ETH_TYPE_CFM && eth_addr_equals(flow->dl_dst, cfm_ccm_addr(cfm)) && (!cfm->check_tnl_key || flow->tunnel.tun_id == htonll(0))); diff --git a/lib/cfm.h b/lib/cfm.h index 057da04b1..15a015486 100644 --- a/lib/cfm.h +++ b/lib/cfm.h @@ -24,6 +24,7 @@ struct flow; struct ofpbuf; struct netdev; +struct flow_wildcards; #define CFM_RANDOM_VLAN UINT16_MAX @@ -72,7 +73,8 @@ void cfm_compose_ccm(struct cfm *, struct ofpbuf *packet, uint8_t eth_src[6]); void cfm_wait(struct cfm *); bool cfm_configure(struct cfm *, const struct cfm_settings *); void cfm_set_netdev(struct cfm *, const struct netdev *); -bool cfm_should_process_flow(const struct cfm *cfm, const struct flow *); +bool cfm_should_process_flow(const struct cfm *cfm, const struct flow *, + struct flow_wildcards *); void cfm_process_heartbeat(struct cfm *, const struct ofpbuf *packet); int cfm_get_fault(const struct cfm *); int cfm_get_health(const struct cfm *); diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index 5118d1720..f5877a46b 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -794,17 +794,20 @@ fix_sflow_action(struct xlate_ctx *ctx) } static enum slow_path_reason -process_special(struct ofproto_dpif *ofproto, const struct flow *flow, +process_special(struct xlate_ctx *ctx, const struct flow *flow, const struct ofport_dpif *ofport, const struct ofpbuf *packet) { + struct ofproto_dpif *ofproto = ctx->ofproto; + struct flow_wildcards *wc = &ctx->xout->wc; + if (!ofport) { return 0; - } else if (ofport->cfm && cfm_should_process_flow(ofport->cfm, flow)) { + } else if (ofport->cfm && cfm_should_process_flow(ofport->cfm, flow, wc)) { if (packet) { cfm_process_heartbeat(ofport->cfm, packet); } return SLOW_CFM; - } else if (ofport->bfd && bfd_should_process_flow(flow)) { + } else if (ofport->bfd && bfd_should_process_flow(flow, wc)) { if (packet) { bfd_process_packet(ofport->bfd, flow, packet); } @@ -815,7 +818,7 @@ process_special(struct ofproto_dpif *ofproto, const struct flow *flow, lacp_process_packet(ofport->bundle->lacp, ofport, packet); } return SLOW_LACP; - } else if (ofproto->stp && stp_should_process_flow(flow)) { + } else if (ofproto->stp && stp_should_process_flow(flow, wc)) { if (packet) { stp_process_packet(ofport, packet); } @@ -868,7 +871,7 @@ compose_output_action__(struct xlate_ctx *ctx, uint16_t ofp_port, memset(&flow->tunnel, 0, sizeof flow->tunnel); memset(flow->regs, 0, sizeof flow->regs); - special = process_special(ctx->ofproto, &ctx->xin->flow, peer, + special = process_special(ctx, &ctx->xin->flow, peer, ctx->xin->packet); if (special) { ctx->xout->slow = special; @@ -1966,7 +1969,7 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout) } in_port = get_ofp_port(ctx.ofproto, flow->in_port); - special = process_special(ctx.ofproto, flow, in_port, ctx.xin->packet); + special = process_special(&ctx, flow, in_port, ctx.xin->packet); if (special) { ctx.xout->slow = special; } else { diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index e9af4a621..194f5bd45 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -1927,10 +1927,12 @@ stp_wait(struct ofproto_dpif *ofproto) } } -/* Returns true if STP should process 'flow'. */ +/* Returns true if STP should process 'flow'. Sets fields in 'wc' that + * were used to make the determination.*/ bool -stp_should_process_flow(const struct flow *flow) +stp_should_process_flow(const struct flow *flow, struct flow_wildcards *wc) { + memset(&wc->masks.dl_dst, 0xff, sizeof wc->masks.dl_dst); return eth_addr_equals(flow->dl_dst, eth_addr_stp); } diff --git a/ofproto/ofproto-dpif.h b/ofproto/ofproto-dpif.h index bfba344fb..3852fa8d8 100644 --- a/ofproto/ofproto-dpif.h +++ b/ofproto/ofproto-dpif.h @@ -257,7 +257,7 @@ size_t put_userspace_action(const struct ofproto_dpif *, const union user_action_cookie *, const size_t cookie_size); -bool stp_should_process_flow(const struct flow *); +bool stp_should_process_flow(const struct flow *, struct flow_wildcards *); void stp_process_packet(const struct ofport_dpif *, const struct ofpbuf *packet);