From 91d6cd12da72f9f0f510c9c66ecb1772197f4678 Mon Sep 17 00:00:00 2001 From: Alex Wang Date: Wed, 9 Oct 2013 04:30:33 +0000 Subject: [PATCH] ofproto-dpif: Move send_packet() to ofproto-dpif-xlate module. This commit moves the main logic of send_packet() function into the ofproto-dpif-xlate module. Also, modification is made to guarantee the thread safety of ofproto-dpif-xlate module. Signed-off-by: Alex Wang Signed-off-by: Ethan Jackson Acked-by: Ben Pfaff Acked-by: Ethan Jackson --- ofproto/ofproto-dpif-xlate.c | 72 +++++++++++++++++++++++++++++++++--- ofproto/ofproto-dpif-xlate.h | 2 + ofproto/ofproto-dpif.c | 62 +++++-------------------------- ofproto/ofproto-dpif.h | 1 + 4 files changed, 80 insertions(+), 57 deletions(-) diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index 930abc31a..de65f6cc7 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -206,6 +206,8 @@ static struct hmap xports = HMAP_INITIALIZER(&xports); static bool may_receive(const struct xport *, struct xlate_ctx *); static void do_xlate_actions(const struct ofpact *, size_t ofpacts_len, struct xlate_ctx *); +static void xlate_actions__(struct xlate_in *, struct xlate_out *) + OVS_REQ_RDLOCK(xlate_rwlock); static void xlate_normal(struct xlate_ctx *); static void xlate_report(struct xlate_ctx *, const char *); static void xlate_table_action(struct xlate_ctx *, ofp_port_t in_port, @@ -2639,13 +2641,23 @@ actions_output_to_local_port(const struct xlate_ctx *ctx) return false; } +/* Thread safe call to xlate_actions__(). */ +void +xlate_actions(struct xlate_in *xin, struct xlate_out *xout) +{ + ovs_rwlock_rdlock(&xlate_rwlock); + xlate_actions__(xin, xout); + ovs_rwlock_unlock(&xlate_rwlock); +} + /* Translates the 'ofpacts_len' bytes of "struct ofpacts" starting at 'ofpacts' * into datapath actions in 'odp_actions', using 'ctx'. * * The caller must take responsibility for eventually freeing 'xout', with * xlate_out_uninit(). */ -void -xlate_actions(struct xlate_in *xin, struct xlate_out *xout) +static void +xlate_actions__(struct xlate_in *xin, struct xlate_out *xout) + OVS_REQ_RDLOCK(xlate_rwlock) { struct flow_wildcards *wc = &xout->wc; struct flow *flow = &xin->flow; @@ -2661,8 +2673,6 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout) COVERAGE_INC(xlate_actions); - ovs_rwlock_rdlock(&xlate_rwlock); - /* Flow initialization rules: * - 'base_flow' must match the kernel's view of the packet at the * time that action processing starts. 'flow' represents any @@ -2825,7 +2835,59 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout) memset(&wc->masks.regs, 0, sizeof wc->masks.regs); out: + rule_actions_unref(actions); +} + +/* Sends 'packet' out 'ofport'. + * May modify 'packet'. + * Returns 0 if successful, otherwise a positive errno value. */ +int +xlate_send_packet(const struct ofport_dpif *ofport, struct ofpbuf *packet) +{ + uint64_t odp_actions_stub[1024 / 8]; + struct xport *xport; + struct ofpbuf key, odp_actions; + struct dpif_flow_stats stats; + struct odputil_keybuf keybuf; + struct ofpact_output output; + struct xlate_out xout; + struct xlate_in xin; + struct flow flow; + union flow_in_port in_port_; + int error; + + ofpbuf_use_stub(&odp_actions, odp_actions_stub, sizeof odp_actions_stub); + ofpbuf_use_stack(&key, &keybuf, sizeof keybuf); + 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); + + ovs_rwlock_rdlock(&xlate_rwlock); + xport = xport_lookup(ofport); + if (!xport) { + error = EINVAL; + ovs_rwlock_unlock(&xlate_rwlock); + goto out; + } + + odp_flow_key_from_flow(&key, &flow, ofp_port_to_odp_port(xport->xbridge, OFPP_LOCAL)); + dpif_flow_stats_extract(&flow, packet, time_msec(), &stats); + output.port = xport->ofp_port; + output.max_len = 0; + xlate_in_init(&xin, xport->xbridge->ofproto, &flow, NULL, 0, packet); + xin.ofpacts_len = sizeof output; + xin.ofpacts = &output.ofpact; + xin.resubmit_stats = &stats; + /* Calls xlate_actions__ directly, since the rdlock is acquired. */ + xlate_actions__(&xin, &xout); + error = dpif_execute(xport->xbridge->dpif, + key.data, key.size, + xout.odp_actions.data, xout.odp_actions.size, + packet); ovs_rwlock_unlock(&xlate_rwlock); - rule_actions_unref(actions); +out: + xlate_out_uninit(&xout); + return error; } diff --git a/ofproto/ofproto-dpif-xlate.h b/ofproto/ofproto-dpif-xlate.h index 6403f50aa..554d46e90 100644 --- a/ofproto/ofproto-dpif-xlate.h +++ b/ofproto/ofproto-dpif-xlate.h @@ -160,4 +160,6 @@ struct dpif_sflow *xlate_get_sflow(const struct ofproto_dpif *) struct dpif_ipfix *xlate_get_ipfix(const struct ofproto_dpif *) OVS_EXCLUDED(xlate_rwlock); +int xlate_send_packet(const struct ofport_dpif *, struct ofpbuf *); + #endif /* ofproto-dpif-xlate.h */ diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 80e97e04c..b45a28940 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -526,9 +526,6 @@ static int expire(struct dpif_backer *); /* NetFlow. */ static void send_netflow_active_timeouts(struct ofproto_dpif *); -/* Utilities. */ -static int send_packet(const struct ofport_dpif *, struct ofpbuf *packet); - /* Global variables. */ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); @@ -1996,7 +1993,7 @@ send_bpdu_cb(struct ofpbuf *pkt, int port_num, void *ofproto_) VLOG_WARN_RL(&rl, "%s: cannot send BPDU on port %d " "with unknown MAC", ofproto->up.name, port_num); } else { - send_packet(ofport, pkt); + ofproto_dpif_send_packet(ofport, pkt); } } ofpbuf_delete(pkt); @@ -2592,7 +2589,7 @@ send_pdu_cb(void *port_, const void *pdu, size_t pdu_size) pdu_size); memcpy(packet_pdu, pdu, pdu_size); - send_packet(port, &packet); + ofproto_dpif_send_packet(port, &packet); ofpbuf_uninit(&packet); } else { VLOG_ERR_RL(&rl, "port %s: cannot obtain Ethernet address of iface " @@ -2629,7 +2626,7 @@ bundle_send_learning_packets(struct ofbundle *bundle) LIST_FOR_EACH (learning_packet, list_node, &packets) { int ret; - ret = send_packet(learning_packet->private_p, learning_packet); + ret = ofproto_dpif_send_packet(learning_packet->private_p, learning_packet); if (ret) { error = ret; n_errors++; @@ -2851,7 +2848,7 @@ port_run_fast(struct ofport_dpif *ofport) ofpbuf_init(&packet, 0); cfm_compose_ccm(ofport->cfm, &packet, ofport->up.pp.hw_addr); - send_packet(ofport, &packet); + ofproto_dpif_send_packet(ofport, &packet); ofpbuf_uninit(&packet); } @@ -2860,7 +2857,7 @@ port_run_fast(struct ofport_dpif *ofport) ofpbuf_init(&packet, 0); bfd_put_packet(ofport->bfd, &packet, ofport->up.pp.hw_addr); - send_packet(ofport, &packet); + ofproto_dpif_send_packet(ofport, &packet); ofpbuf_uninit(&packet); } } @@ -3040,8 +3037,8 @@ port_get_stats(const struct ofport *ofport_, struct netdev_stats *stats) /* ofproto->stats.tx_packets represents packets that we created * internally and sent to some port (e.g. packets sent with - * send_packet()). Account for them as if they had come from - * OFPP_LOCAL and got forwarded. */ + * ofproto_dpif_send_packet()). Account for them as if they had + * come from OFPP_LOCAL and got forwarded. */ if (stats->rx_packets != UINT64_MAX) { stats->rx_packets += ofproto->stats.tx_packets; @@ -4825,52 +4822,13 @@ rule_modify_actions(struct rule *rule_, bool reset_counters) /* Sends 'packet' out 'ofport'. * May modify 'packet'. * Returns 0 if successful, otherwise a positive errno value. */ -static int -send_packet(const struct ofport_dpif *ofport, struct ofpbuf *packet) +int +ofproto_dpif_send_packet(const struct ofport_dpif *ofport, struct ofpbuf *packet) { struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofport->up.ofproto); - uint64_t odp_actions_stub[1024 / 8]; - struct ofpbuf key, odp_actions; - struct dpif_flow_stats stats; - struct odputil_keybuf keybuf; - struct ofpact_output output; - struct xlate_out xout; - struct xlate_in xin; - struct flow flow; - union flow_in_port in_port_; int error; - ofpbuf_use_stub(&odp_actions, odp_actions_stub, sizeof odp_actions_stub); - ofpbuf_use_stack(&key, &keybuf, sizeof keybuf); - - /* 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); - odp_flow_key_from_flow(&key, &flow, ofp_port_to_odp_port(ofproto, - OFPP_LOCAL)); - dpif_flow_stats_extract(&flow, packet, time_msec(), &stats); - - ofpact_init(&output.ofpact, OFPACT_OUTPUT, sizeof output); - output.port = ofport->up.ofp_port; - output.max_len = 0; - - xlate_in_init(&xin, ofproto, &flow, NULL, 0, packet); - xin.ofpacts_len = sizeof output; - xin.ofpacts = &output.ofpact; - xin.resubmit_stats = &stats; - xlate_actions(&xin, &xout); - - error = dpif_execute(ofproto->backer->dpif, - key.data, key.size, - xout.odp_actions.data, xout.odp_actions.size, - packet); - xlate_out_uninit(&xout); - - if (error) { - VLOG_WARN_RL(&rl, "%s: failed to send packet on port %s (%s)", - ofproto->up.name, netdev_get_name(ofport->up.netdev), - ovs_strerror(error)); - } + error = xlate_send_packet(ofport, packet); ofproto->stats.tx_packets++; ofproto->stats.tx_bytes += packet->size; diff --git a/ofproto/ofproto-dpif.h b/ofproto/ofproto-dpif.h index 14a96693b..0863efda2 100644 --- a/ofproto/ofproto-dpif.h +++ b/ofproto/ofproto-dpif.h @@ -95,6 +95,7 @@ bool vsp_adjust_flow(const struct ofproto_dpif *, struct flow *); void ofproto_dpif_send_packet_in(struct ofproto_dpif *, struct ofputil_packet_in *pin); +int ofproto_dpif_send_packet(const struct ofport_dpif *, struct ofpbuf *); void ofproto_dpif_flow_mod(struct ofproto_dpif *, struct ofputil_flow_mod *); struct ofport_dpif *odp_port_to_ofport(const struct dpif_backer *, odp_port_t); -- 2.43.0