X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=ofproto%2Fofproto-dpif-upcall.c;h=dd24f5cb112a732ba973ccff5d34cebbdc79e558;hb=37bec3d330ed7f72b6a867728c538b49e5727dc7;hp=78424fd428bfd3d51bd3e30ac1ad0851f65d4b21;hpb=e79a6c833e0d72370951d6f8841098103cbb0b2d;p=sliver-openvswitch.git diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c index 78424fd42..dd24f5cb1 100644 --- a/ofproto/ofproto-dpif-upcall.c +++ b/ofproto/ofproto-dpif-upcall.c @@ -273,6 +273,8 @@ udpif_destroy(struct udpif *udpif) latch_destroy(&udpif->exit_latch); seq_destroy(udpif->reval_seq); seq_destroy(udpif->dump_seq); + atomic_destroy(&udpif->max_idle); + atomic_destroy(&udpif->flow_limit); free(udpif); } @@ -601,7 +603,7 @@ udpif_flow_dumper(void *arg) atomic_store(&udpif->flow_limit, flow_limit); if (duration > 2000) { - VLOG_WARN("Spent an unreasonably long %lldms dumping flows", + VLOG_INFO("Spent an unreasonably long %lldms dumping flows", duration); } @@ -625,17 +627,11 @@ udpif_upcall_handler(void *arg) handler->name = xasprintf("handler_%u", ovsthread_id_self()); set_subprogram_name("%s", handler->name); - for (;;) { + while (!latch_is_set(&handler->udpif->exit_latch)) { struct list misses = LIST_INITIALIZER(&misses); size_t i; ovs_mutex_lock(&handler->mutex); - - if (latch_is_set(&handler->udpif->exit_latch)) { - ovs_mutex_unlock(&handler->mutex); - return NULL; - } - if (!handler->n_upcalls) { ovs_mutex_cond_wait(&handler->wake_cond, &handler->mutex); } @@ -654,6 +650,8 @@ udpif_upcall_handler(void *arg) coverage_clear(); } + + return NULL; } static void * @@ -1076,9 +1074,12 @@ handle_upcalls(struct handler *handler, struct list *upcalls) LIST_FOR_EACH (upcall, list_node, upcalls) { struct flow_miss *miss = upcall->flow_miss; struct ofpbuf *packet = &upcall->dpif_upcall.packet; - struct ofpbuf mask; struct dpif_op *op; - bool megaflow; + ovs_be16 flow_vlan_tci; + + /* Save a copy of flow.vlan_tci in case it is changed to + * generate proper mega flow masks for VLAN splinter flows. */ + flow_vlan_tci = miss->flow.vlan_tci; if (miss->xout.slow) { struct xlate_in xin; @@ -1087,14 +1088,36 @@ handle_upcalls(struct handler *handler, struct list *upcalls) xlate_actions_for_side_effects(&xin); } - atomic_read(&enable_megaflows, &megaflow); - ofpbuf_use_stack(&mask, &miss->mask_buf, sizeof miss->mask_buf); - if (megaflow) { - odp_flow_key_from_mask(&mask, &miss->xout.wc.masks, &miss->flow, - UINT32_MAX); + if (miss->flow.in_port.ofp_port + != vsp_realdev_to_vlandev(miss->ofproto, + miss->flow.in_port.ofp_port, + miss->flow.vlan_tci)) { + /* This packet was received on a VLAN splinter port. We + * added a VLAN to the packet to make the packet resemble + * the flow, but the actions were composed assuming that + * the packet contained no VLAN. So, we must remove the + * VLAN header from the packet before trying to execute the + * actions. */ + if (miss->xout.odp_actions.size) { + eth_pop_vlan(packet); + } + + /* Remove the flow vlan tags inserted by vlan splinter logic + * to ensure megaflow masks generated match the data path flow. */ + miss->flow.vlan_tci = 0; } if (may_put) { + struct ofpbuf mask; + bool megaflow; + + atomic_read(&enable_megaflows, &megaflow); + ofpbuf_use_stack(&mask, &miss->mask_buf, sizeof miss->mask_buf); + if (megaflow) { + odp_flow_key_from_mask(&mask, &miss->xout.wc.masks, + &miss->flow, UINT32_MAX); + } + op = &ops[n_ops++]; op->type = DPIF_OP_FLOW_PUT; op->u.flow_put.flags = DPIF_FP_CREATE | DPIF_FP_MODIFY; @@ -1118,25 +1141,19 @@ handle_upcalls(struct handler *handler, struct list *upcalls) } } + /* + * The 'miss' may be shared by multiple upcalls. Restore + * the saved flow vlan_tci field before processing the next + * upcall. */ + miss->flow.vlan_tci = flow_vlan_tci; + if (miss->xout.odp_actions.size) { - if (miss->flow.in_port.ofp_port - != vsp_realdev_to_vlandev(miss->ofproto, - miss->flow.in_port.ofp_port, - miss->flow.vlan_tci)) { - /* This packet was received on a VLAN splinter port. We - * added a VLAN to the packet to make the packet resemble - * the flow, but the actions were composed assuming that - * the packet contained no VLAN. So, we must remove the - * VLAN header from the packet before trying to execute the - * actions. */ - eth_pop_vlan(packet); - } op = &ops[n_ops++]; op->type = DPIF_OP_EXECUTE; - op->u.execute.key = miss->key; - op->u.execute.key_len = miss->key_len; op->u.execute.packet = packet; + odp_key_to_pkt_metadata(miss->key, miss->key_len, + &op->u.execute.md); op->u.execute.actions = miss->xout.odp_actions.data; op->u.execute.actions_len = miss->xout.odp_actions.size; op->u.execute.needs_help = (miss->xout.slow & SLOW_ACTION) != 0;