From 62a7cc71f56ff6a2e943db3d1db238bf7ecd8bc9 Mon Sep 17 00:00:00 2001 From: Jesse Gross Date: Tue, 6 Aug 2013 12:57:14 -0700 Subject: [PATCH] tunnel: Consolidate action code for tunnel port receive. There are a couple of operations that are related to receiving a packet on a tunnel port but that affect the actions and therefore need to be performed on the output path. This adds a new hook to do this and consolidates the existing code there. Signed-off-by: Jesse Gross Acked-by: Andy Zhou --- ofproto/ofproto-dpif-xlate.c | 30 +++------------------------- ofproto/tunnel.c | 38 ++++++++++++++++++++++++++++++++++++ ofproto/tunnel.h | 2 ++ 3 files changed, 43 insertions(+), 27 deletions(-) diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index 5c704e48e..0f4a10c35 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -201,8 +201,6 @@ static void output_normal(struct xlate_ctx *, const struct xbundle *, uint16_t vlan); static void compose_output_action(struct xlate_ctx *, ofp_port_t ofp_port); -static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); - static struct xbridge *xbridge_lookup(const struct ofproto_dpif *); static struct xbundle *xbundle_lookup(const struct ofbundle *); static struct xport *xport_lookup(const struct ofport_dpif *); @@ -2171,24 +2169,6 @@ may_receive(const struct xport *xport, struct xlate_ctx *ctx) return true; } -static bool -tunnel_ecn_ok(struct xlate_ctx *ctx) -{ - if (is_ip_any(&ctx->base_flow) - && (ctx->xin->flow.tunnel.ip_tos & IP_ECN_MASK) == IP_ECN_CE) { - if ((ctx->base_flow.nw_tos & IP_ECN_MASK) == IP_ECN_NOT_ECT) { - VLOG_WARN_RL(&rl, "dropping tunnel packet marked ECN CE" - " but is not ECN capable"); - return false; - } else { - /* Set the ECN CE value in the tunneled packet. */ - ctx->xin->flow.nw_tos |= IP_ECN_CE; - } - } - - return true; -} - static void do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, struct xlate_ctx *ctx) @@ -2552,6 +2532,7 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout) struct flow orig_flow; struct xlate_ctx ctx; size_t ofpacts_len; + bool tnl_may_send; COVERAGE_INC(xlate_actions); @@ -2607,12 +2588,7 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout) memset(&wc->masks.dl_type, 0xff, sizeof wc->masks.dl_type); wc->masks.nw_frag |= FLOW_NW_FRAG_MASK; - if (tnl_port_should_receive(&ctx.xin->flow)) { - memset(&wc->masks.tunnel, 0xff, sizeof wc->masks.tunnel); - /* pkt_mark is currently used only by tunnels but that will likely - * change in the future. */ - memset(&wc->masks.pkt_mark, 0xff, sizeof wc->masks.pkt_mark); - } + tnl_may_send = tnl_xlate_init(&ctx.base_flow, flow, wc); if (ctx.xbridge->has_netflow) { netflow_mask_wc(flow, wc); } @@ -2681,7 +2657,7 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout) add_ipfix_action(&ctx); sample_actions_len = ctx.xout->odp_actions.size; - if (tunnel_ecn_ok(&ctx) && (!in_port || may_receive(in_port, &ctx))) { + if (tnl_may_send && (!in_port || may_receive(in_port, &ctx))) { do_xlate_actions(ofpacts, ofpacts_len, &ctx); /* We've let OFPP_NORMAL and the learning action look at the diff --git a/ofproto/tunnel.c b/ofproto/tunnel.c index bcc90cab2..8b49d6a45 100644 --- a/ofproto/tunnel.c +++ b/ofproto/tunnel.c @@ -249,6 +249,44 @@ out: return ofport; } +static bool +tnl_ecn_ok(const struct flow *base_flow, struct flow *flow) +{ + if (is_ip_any(base_flow) + && (flow->tunnel.ip_tos & IP_ECN_MASK) == IP_ECN_CE) { + if ((base_flow->nw_tos & IP_ECN_MASK) == IP_ECN_NOT_ECT) { + VLOG_WARN_RL(&rl, "dropping tunnel packet marked ECN CE" + " but is not ECN capable"); + return false; + } else { + /* Set the ECN CE value in the tunneled packet. */ + flow->nw_tos |= IP_ECN_CE; + } + } + + return true; +} + +/* Should be called at the beginning of action translation to initialize + * wildcards and perform any actions based on receiving on tunnel port. + * + * Returns false if the packet must be dropped. */ +bool +tnl_xlate_init(const struct flow *base_flow, struct flow *flow, + struct flow_wildcards *wc) +{ + if (tnl_port_should_receive(flow)) { + memset(&wc->masks.tunnel, 0xff, sizeof wc->masks.tunnel); + memset(&wc->masks.pkt_mark, 0xff, sizeof wc->masks.pkt_mark); + + if (!tnl_ecn_ok(base_flow, flow)) { + return false; + } + } + + return true; +} + /* Given that 'flow' should be output to the ofport corresponding to * 'tnl_port', updates 'flow''s tunnel headers and returns the actual datapath * port that the output should happen on. May return ODPP_NONE if the output diff --git a/ofproto/tunnel.h b/ofproto/tunnel.h index f175f1a15..afe78ab80 100644 --- a/ofproto/tunnel.h +++ b/ofproto/tunnel.h @@ -39,6 +39,8 @@ void tnl_port_add(const struct ofport_dpif *, const struct netdev *, void tnl_port_del(const struct ofport_dpif *); const struct ofport_dpif *tnl_port_receive(const struct flow *); +bool tnl_xlate_init(const struct flow *base_flow, struct flow *flow, + struct flow_wildcards *); odp_port_t tnl_port_send(const struct ofport_dpif *, struct flow *, struct flow_wildcards *wc); -- 2.43.0