X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=ofproto%2Fofproto-dpif-xlate.c;h=4747ea7e0ec9e11a6bec44ee649bdf614747a981;hb=e491a67a00053471300dd7ef6466bb66ff68de3b;hp=402f54bcf4b8d3157b98a761b28d53ddec776357;hpb=d6fc5f57bb57fede0ddad2272a734a6212eda6b2;p=sliver-openvswitch.git diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index 402f54bcf..4747ea7e0 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2009, 2010, 2011, 2012, 2013 Nicira, Inc. +/* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,6 +42,7 @@ #include "ofp-actions.h" #include "ofproto/ofproto-dpif-ipfix.h" #include "ofproto/ofproto-dpif-mirror.h" +#include "ofproto/ofproto-dpif-monitor.h" #include "ofproto/ofproto-dpif-sflow.h" #include "ofproto/ofproto-dpif.h" #include "ofproto/ofproto-provider.h" @@ -86,6 +87,11 @@ struct xbridge { enum ofp_config_flags frag; /* Fragmentation handling. */ bool has_in_band; /* Bridge has in band control? */ bool forward_bpdu; /* Bridge forwards STP BPDUs? */ + + /* True if the datapath supports variable-length + * OVS_USERSPACE_ATTR_USERDATA in OVS_ACTION_ATTR_USERSPACE actions. + * False if the datapath supports only 8-byte (or shorter) userdata. */ + bool variable_length_userdata; }; struct xbundle { @@ -248,7 +254,8 @@ xlate_ofproto_set(struct ofproto_dpif *ofproto, const char *name, const struct dpif_sflow *sflow, const struct dpif_ipfix *ipfix, const struct netflow *netflow, enum ofp_config_flags frag, - bool forward_bpdu, bool has_in_band) + bool forward_bpdu, bool has_in_band, + bool variable_length_userdata) { struct xbridge *xbridge = xbridge_lookup(ofproto); @@ -300,6 +307,7 @@ xlate_ofproto_set(struct ofproto_dpif *ofproto, const char *name, xbridge->frag = frag; xbridge->miss_rule = miss_rule; xbridge->no_packet_in_rule = no_packet_in_rule; + xbridge->variable_length_userdata = variable_length_userdata; } void @@ -572,18 +580,7 @@ xlate_receive(const struct dpif_backer *backer, struct ofpbuf *packet, /* Make the packet resemble the flow, so that it gets sent to * an OpenFlow controller properly, so that it looks correct * for sFlow, and so that flow_extract() will get the correct - * vlan_tci if it is called on 'packet'. - * - * The allocated space inside 'packet' probably also contains - * 'key', that is, both 'packet' and 'key' are probably part of - * a struct dpif_upcall (see the large comment on that - * structure definition), so pushing data on 'packet' is in - * general not a good idea since it could overwrite 'key' or - * free it as a side effect. However, it's OK in this special - * case because we know that 'packet' is inside a Netlink - * attribute: pushing 4 bytes will just overwrite the 4-byte - * "struct nlattr", which is fine since we don't need that - * header anymore. */ + * vlan_tci if it is called on 'packet'. */ eth_push_vlan(packet, flow->vlan_tci); } /* We can't reproduce 'key' from 'flow'. */ @@ -979,7 +976,7 @@ add_mirror_actions(struct xlate_ctx *ctx, const struct flow *orig_flow) bool has_mirror; int out_vlan; - has_mirror = mirror_get(xbridge->mbridge, mirror_mask_ffs(mirrors) - 1, + has_mirror = mirror_get(xbridge->mbridge, raw_ctz(mirrors), &vlans, &dup_mirrors, &out, &out_vlan); ovs_assert(has_mirror); @@ -1037,7 +1034,7 @@ input_vid_to_vlan(const struct xbundle *in_xbundle, uint16_t vid) return vid ? vid : in_xbundle->vlan; default: - NOT_REACHED(); + OVS_NOT_REACHED(); } } @@ -1090,7 +1087,7 @@ input_vid_is_valid(uint16_t vid, struct xbundle *in_xbundle, bool warn) return true; default: - NOT_REACHED(); + OVS_NOT_REACHED(); } } @@ -1117,7 +1114,7 @@ output_vlan_to_vid(const struct xbundle *out_xbundle, uint16_t vlan) return vlan == out_xbundle->vlan ? 0 : vlan; default: - NOT_REACHED(); + OVS_NOT_REACHED(); } } @@ -1656,6 +1653,14 @@ process_special(struct xlate_ctx *ctx, const struct flow *flow, } else if (xport->bfd && bfd_should_process_flow(xport->bfd, flow, wc)) { if (packet) { bfd_process_packet(xport->bfd, flow, packet); + /* If POLL received, immediately sends FINAL back. */ + if (bfd_should_send_packet(xport->bfd)) { + if (xport->peer) { + ofproto_dpif_monitor_port_send_soon(xport->ofport); + } else { + ofproto_dpif_monitor_port_send_soon_safe(xport->ofport); + } + } } return SLOW_BFD; } else if (xport->xbundle && xport->xbundle->lacp @@ -1873,9 +1878,10 @@ xlate_table_action(struct xlate_ctx *ctx, ofp_port_t in_port, uint8_t table_id, bool may_packet_in) { if (xlate_resubmit_resource_check(ctx)) { - struct rule_dpif *rule; ofp_port_t old_in_port = ctx->xin->flow.in_port.ofp_port; + bool skip_wildcards = ctx->xin->skip_wildcards; uint8_t old_table_id = ctx->table_id; + struct rule_dpif *rule; ctx->table_id = table_id; @@ -1883,8 +1889,8 @@ xlate_table_action(struct xlate_ctx *ctx, * original input port (otherwise OFPP_NORMAL and OFPP_IN_PORT will * have surprising behavior). */ ctx->xin->flow.in_port.ofp_port = in_port; - rule_dpif_lookup_in_table(ctx->xbridge->ofproto, - &ctx->xin->flow, &ctx->xout->wc, + rule_dpif_lookup_in_table(ctx->xbridge->ofproto, &ctx->xin->flow, + !skip_wildcards ? &ctx->xout->wc : NULL, table_id, &rule); ctx->xin->flow.in_port.ofp_port = old_in_port; @@ -1998,7 +2004,7 @@ xlate_group_action__(struct xlate_ctx *ctx, struct group_dpif *group) xlate_ff_group(ctx, group); break; default: - NOT_REACHED(); + OVS_NOT_REACHED(); } group_dpif_release(group); } @@ -2068,7 +2074,7 @@ execute_controller_action(struct xlate_ctx *ctx, int len, { struct ofproto_packet_in *pin; struct ofpbuf *packet; - struct flow key; + struct pkt_metadata md = PKT_METADATA_INITIALIZER(0); ctx->xout->slow |= SLOW_CONTROLLER; if (!ctx->xin->packet) { @@ -2077,17 +2083,13 @@ execute_controller_action(struct xlate_ctx *ctx, int len, packet = ofpbuf_clone(ctx->xin->packet); - key.skb_priority = 0; - key.pkt_mark = 0; - memset(&key.tunnel, 0, sizeof key.tunnel); - ctx->xout->slow |= commit_odp_actions(&ctx->xin->flow, &ctx->base_flow, &ctx->xout->odp_actions, &ctx->xout->wc, &ctx->mpls_depth_delta); - odp_execute_actions(NULL, packet, &key, ctx->xout->odp_actions.data, - ctx->xout->odp_actions.size, NULL, NULL); + odp_execute_actions(NULL, packet, &md, ctx->xout->odp_actions.data, + ctx->xout->odp_actions.size, NULL); pin = xmalloc(sizeof *pin); pin->up.packet_len = packet->size; @@ -2522,6 +2524,15 @@ xlate_sample_action(struct xlate_ctx *ctx, * the same percentage. */ uint32_t probability = (os->probability << 16) | os->probability; + if (!ctx->xbridge->variable_length_userdata) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); + + VLOG_ERR_RL(&rl, "ignoring NXAST_SAMPLE action because datapath " + "lacks support (needs Linux 3.10+ or kernel module from " + "OVS 1.11+)"); + return; + } + ctx->xout->slow |= commit_odp_actions(&ctx->xin->flow, &ctx->base_flow, &ctx->xout->odp_actions, &ctx->xout->wc, @@ -2743,7 +2754,7 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, * applicable header fields. Do nothing if no header exists. */ if ((mf->id != MFF_VLAN_VID || flow->vlan_tci & htons(VLAN_CFI)) && ((mf->id != MFF_MPLS_LABEL && mf->id != MFF_MPLS_TC) - || flow->mpls_lse)) { + || eth_type_mpls(flow->dl_type))) { mf_set_flow_value(mf, &set_field->value, flow); } break; @@ -2886,6 +2897,7 @@ xlate_in_init(struct xlate_in *xin, struct ofproto_dpif *ofproto, xin->resubmit_hook = NULL; xin->report_hook = NULL; xin->resubmit_stats = NULL; + xin->skip_wildcards = false; } void @@ -3065,7 +3077,9 @@ xlate_actions__(struct xlate_in *xin, struct xlate_out *xout) memset(&wc->masks.in_port, 0xff, sizeof wc->masks.in_port); memset(&wc->masks.skb_priority, 0xff, sizeof wc->masks.skb_priority); memset(&wc->masks.dl_type, 0xff, sizeof wc->masks.dl_type); - wc->masks.nw_frag |= FLOW_NW_FRAG_MASK; + if (is_ip_any(flow)) { + wc->masks.nw_frag |= FLOW_NW_FRAG_MASK; + } tnl_may_send = tnl_xlate_init(&ctx.base_flow, flow, wc); if (ctx.xbridge->netflow) { @@ -3080,7 +3094,8 @@ xlate_actions__(struct xlate_in *xin, struct xlate_out *xout) ctx.mpls_depth_delta = 0; if (!xin->ofpacts && !ctx.rule) { - rule_dpif_lookup(ctx.xbridge->ofproto, flow, wc, &rule); + rule_dpif_lookup(ctx.xbridge->ofproto, flow, + !xin->skip_wildcards ? wc : NULL, &rule); if (ctx.xin->resubmit_stats) { rule_dpif_credit_stats(rule, ctx.xin->resubmit_stats); } @@ -3096,7 +3111,7 @@ xlate_actions__(struct xlate_in *xin, struct xlate_out *xout) ofpacts = actions->ofpacts; ofpacts_len = actions->ofpacts_len; } else { - NOT_REACHED(); + OVS_NOT_REACHED(); } ofpbuf_use_stub(&ctx.stack, ctx.init_stack, sizeof ctx.init_stack); @@ -3121,14 +3136,14 @@ xlate_actions__(struct xlate_in *xin, struct xlate_out *xout) goto out; case OFPC_FRAG_REASM: - NOT_REACHED(); + OVS_NOT_REACHED(); case OFPC_FRAG_NX_MATCH: /* Nothing to do. */ break; case OFPC_INVALID_TTL_TO_CONTROLLER: - NOT_REACHED(); + OVS_NOT_REACHED(); } } @@ -3240,7 +3255,6 @@ xlate_send_packet(const struct ofport_dpif *ofport, struct ofpbuf *packet) struct ofpact_output output; struct flow flow; union flow_in_port in_port_; - int error; ofpact_init(&output.ofpact, OFPACT_OUTPUT, sizeof output); /* Use OFPP_NONE as the in_port to avoid special packet processing. */ @@ -3255,9 +3269,9 @@ xlate_send_packet(const struct ofport_dpif *ofport, struct ofpbuf *packet) } output.port = xport->ofp_port; output.max_len = 0; - error = ofproto_dpif_execute_actions(xport->xbridge->ofproto, &flow, NULL, - &output.ofpact, sizeof output, - packet); ovs_rwlock_unlock(&xlate_rwlock); - return error; + + return ofproto_dpif_execute_actions(xport->xbridge->ofproto, &flow, NULL, + &output.ofpact, sizeof output, + packet); }