diff options
Diffstat (limited to 'ofproto')
-rw-r--r-- | ofproto/automake.mk | 2 | ||||
-rw-r--r-- | ofproto/ofproto-dpif-elephant.c | 58 | ||||
-rw-r--r-- | ofproto/ofproto-dpif-elephant.h | 40 | ||||
-rw-r--r-- | ofproto/ofproto-dpif-xlate.c | 70 | ||||
-rw-r--r-- | ofproto/ofproto-dpif-xlate.h | 6 | ||||
-rw-r--r-- | ofproto/ofproto-dpif.c | 41 | ||||
-rw-r--r-- | ofproto/ofproto-dpif.h | 2 | ||||
-rw-r--r-- | ofproto/ofproto-provider.h | 14 | ||||
-rw-r--r-- | ofproto/ofproto.c | 19 | ||||
-rw-r--r-- | ofproto/ofproto.h | 3 |
10 files changed, 246 insertions, 9 deletions
diff --git a/ofproto/automake.mk b/ofproto/automake.mk index 22c50d10a..2f07f6c8d 100644 --- a/ofproto/automake.mk +++ b/ofproto/automake.mk @@ -25,6 +25,8 @@ ofproto_libofproto_la_SOURCES = \ ofproto/ofproto.h \ ofproto/ofproto-dpif.c \ ofproto/ofproto-dpif.h \ + ofproto/ofproto-dpif-elephant.c \ + ofproto/ofproto-dpif-elephant.h \ ofproto/ofproto-dpif-ipfix.c \ ofproto/ofproto-dpif-ipfix.h \ ofproto/ofproto-dpif-mirror.c \ diff --git a/ofproto/ofproto-dpif-elephant.c b/ofproto/ofproto-dpif-elephant.c new file mode 100644 index 000000000..d6bfd1df9 --- /dev/null +++ b/ofproto/ofproto-dpif-elephant.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 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. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <config.h> +#include "ofproto-dpif-elephant.h" +#include "ofproto.h" + +struct dpif_elephant * +dpif_elephant_create(void) +{ + struct dpif_elephant *de; + de = xzalloc(sizeof *de); + ovs_refcount_init(&de->ref_cnt); + return de; +} + +struct dpif_elephant * +dpif_elephant_ref(const struct dpif_elephant *de_) +{ + struct dpif_elephant *de = CONST_CAST(struct dpif_elephant *, de_); + if (de) { + ovs_refcount_ref(&de->ref_cnt); + } + return de; +} + +void +dpif_elephant_unref(struct dpif_elephant *de) +{ + if (de && ovs_refcount_unref(&de->ref_cnt) == 1) { + /* xxx Do we need to blow away the kernel flows? */ + free(de); + } +} + +void +dpif_elephant_set_options(struct dpif_elephant *elephant, uint64_t mech, + uint64_t arg1, uint64_t arg2, int dscp) +{ + /* xxx Do we need to blow away the kernel flows? */ + elephant->mech = mech; + elephant->arg1 = arg1; + elephant->arg2 = arg2; + elephant->dscp = dscp; +} diff --git a/ofproto/ofproto-dpif-elephant.h b/ofproto/ofproto-dpif-elephant.h new file mode 100644 index 000000000..6b7c734e4 --- /dev/null +++ b/ofproto/ofproto-dpif-elephant.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 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. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OFPROTO_ELEPHANT_H +#define OFPROTO_ELEPHANT_H 1 + +#include <stdint.h> +#include "ovs-atomic.h" + +/* xxx Do we want to define this here or in the C file? */ +struct dpif_elephant { + uint32_t mech; + uint32_t arg1; + uint32_t arg2; + int dscp; + + struct ovs_refcount ref_cnt; +}; + +struct dpif_elephant *dpif_elephant_create(void); +struct dpif_elephant *dpif_elephant_ref(const struct dpif_elephant *); +void dpif_elephant_unref(struct dpif_elephant *); + +void dpif_elephant_set_options(struct dpif_elephant *, uint64_t mech, + uint64_t arg1, uint64_t arg2, int dscp); + +#endif /* elephant.h */ diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index 4aedb5914..129cf378d 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -41,6 +41,7 @@ #include "nx-match.h" #include "odp-execute.h" #include "ofp-actions.h" +#include "ofproto/ofproto-dpif-elephant.h" #include "ofproto/ofproto-dpif-ipfix.h" #include "ofproto/ofproto-dpif-mirror.h" #include "ofproto/ofproto-dpif-monitor.h" @@ -86,6 +87,7 @@ struct xbridge { struct dpif_ipfix *ipfix; /* Ipfix handle, or null. */ struct netflow *netflow; /* Netflow handle, or null. */ struct stp *stp; /* STP or null if disabled. */ + struct dpif_elephant *elephant; /* Elephant flow detection, or null. */ /* Special rules installed by ofproto-dpif. */ struct rule_dpif *miss_rule; @@ -360,6 +362,7 @@ static void xlate_xbridge_set(struct xbridge *xbridge, const struct mac_learning *ml, struct stp *stp, const struct mcast_snooping *ms, const struct mbridge *mbridge, + const struct dpif_elephant *elephant, const struct dpif_sflow *sflow, const struct dpif_ipfix *ipfix, const struct netflow *netflow, @@ -425,6 +428,7 @@ xlate_xbridge_set(struct xbridge *xbridge, const struct mac_learning *ml, struct stp *stp, const struct mcast_snooping *ms, const struct mbridge *mbridge, + const struct dpif_elephant *elephant, const struct dpif_sflow *sflow, const struct dpif_ipfix *ipfix, const struct netflow *netflow, enum ofp_config_flags frag, @@ -468,6 +472,11 @@ xlate_xbridge_set(struct xbridge *xbridge, xbridge->netflow = netflow_ref(netflow); } + if (xbridge->elephant != elephant) { + dpif_elephant_unref(xbridge->elephant); + xbridge->elephant = dpif_elephant_ref(elephant); + } + xbridge->dpif = dpif; xbridge->forward_bpdu = forward_bpdu; xbridge->has_in_band = has_in_band; @@ -548,10 +557,11 @@ xlate_xbridge_copy(struct xbridge *xbridge) xlate_xbridge_set(new_xbridge, xbridge->dpif, xbridge->miss_rule, xbridge->no_packet_in_rule, xbridge->ml, xbridge->stp, - xbridge->ms, xbridge->mbridge, xbridge->sflow, - xbridge->ipfix, xbridge->netflow, xbridge->frag, - xbridge->forward_bpdu, xbridge->has_in_band, - xbridge->enable_recirc, xbridge->variable_length_userdata, + xbridge->ms, xbridge->mbridge, xbridge->elephant, + xbridge->sflow, xbridge->ipfix, + xbridge->netflow, xbridge->frag, xbridge->forward_bpdu, + xbridge->has_in_band, xbridge->enable_recirc, + xbridge->variable_length_userdata, xbridge->max_mpls_depth); LIST_FOR_EACH (xbundle, list_node, &xbridge->xbundles) { xlate_xbundle_copy(new_xbridge, xbundle); @@ -700,6 +710,7 @@ xlate_ofproto_set(struct ofproto_dpif *ofproto, const char *name, const struct mac_learning *ml, struct stp *stp, const struct mcast_snooping *ms, const struct mbridge *mbridge, + const struct dpif_elephant *elephant, const struct dpif_sflow *sflow, const struct dpif_ipfix *ipfix, const struct netflow *netflow, enum ofp_config_flags frag, @@ -724,9 +735,9 @@ xlate_ofproto_set(struct ofproto_dpif *ofproto, const char *name, xbridge->name = xstrdup(name); xlate_xbridge_set(xbridge, dpif, miss_rule, no_packet_in_rule, ml, stp, - ms, mbridge, sflow, ipfix, netflow, frag, forward_bpdu, - has_in_band, enable_recirc, variable_length_userdata, - max_mpls_depth); + ms, mbridge, elephant, sflow, ipfix, netflow, frag, + forward_bpdu, has_in_band, enable_recirc, + variable_length_userdata, max_mpls_depth); } static void @@ -754,6 +765,7 @@ xlate_xbridge_remove(struct xlate_cfg *xcfg, struct xbridge *xbridge) dpif_sflow_unref(xbridge->sflow); dpif_ipfix_unref(xbridge->ipfix); stp_unref(xbridge->stp); + dpif_elephant_unref(xbridge->elephant); hmap_destroy(&xbridge->xports); free(xbridge->name); free(xbridge); @@ -2312,6 +2324,48 @@ fix_sflow_action(struct xlate_ctx *ctx) ctx->sflow_odp_port, ctx->sflow_n_outputs, cookie); } +static void +add_elephant_action(struct xlate_ctx *ctx) +{ + const struct xbridge *xbridge = ctx->xbridge; + struct ofpbuf *odp_actions = &ctx->xout->odp_actions; + size_t elephant_offset, actions_offset; +#if 0 + int cookie_offset; + uint32_t pid; +#endif + + if (!xbridge->elephant) { + return; + } + + elephant_offset = nl_msg_start_nested(odp_actions, + OVS_ACTION_ATTR_ELEPHANT); + + nl_msg_put_u32(odp_actions, OVS_ELEPHANT_ATTR_DETECT_MECH, + xbridge->elephant->mech); + nl_msg_put_u32(odp_actions, OVS_ELEPHANT_ATTR_DETECT_ARG1, + xbridge->elephant->arg1); + nl_msg_put_u32(odp_actions, OVS_ELEPHANT_ATTR_DETECT_ARG2, + xbridge->elephant->arg2); + nl_msg_put_u8(odp_actions, OVS_ELEPHANT_ATTR_DETECT_DSCP, + xbridge->elephant->dscp); + + actions_offset = nl_msg_start_nested(odp_actions, + OVS_ELEPHANT_ATTR_ACTIONS); + +#if 0 + odp_port = ofp_port_to_odp_port(xbridge, flow->in_port.ofp_port); + pid = dpif_port_get_pid(xbridge->dpif, odp_port, + flow_hash_5tuple(flow, 0)); + cookie_offset = odp_put_userspace_action(pid, cookie, cookie_size, + odp_actions); +#endif + + nl_msg_end_nested(odp_actions, actions_offset); + nl_msg_end_nested(odp_actions, elephant_offset); +} + static enum slow_path_reason process_special(struct xlate_ctx *ctx, const struct flow *flow, const struct xport *xport, const struct ofpbuf *packet) @@ -4084,6 +4138,8 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout) add_ipfix_action(&ctx); sample_actions_len = ofpbuf_size(&ctx.xout->odp_actions); + add_elephant_action(&ctx); + if (tnl_may_send && (!in_port || may_receive(in_port, &ctx))) { do_xlate_actions(ofpacts, ofpacts_len, &ctx); diff --git a/ofproto/ofproto-dpif-xlate.h b/ofproto/ofproto-dpif-xlate.h index 4bdf2d3e8..ffb6018d9 100644 --- a/ofproto/ofproto-dpif-xlate.h +++ b/ofproto/ofproto-dpif-xlate.h @@ -28,6 +28,7 @@ struct bfd; struct bond; struct dpif; struct lacp; +struct dpif_elephant; struct dpif_ipfix; struct dpif_sflow; struct mac_learning; @@ -142,8 +143,9 @@ void xlate_ofproto_set(struct ofproto_dpif *, const char *name, struct rule_dpif *no_packet_in_rule, const struct mac_learning *, struct stp *, const struct mcast_snooping *, - const struct mbridge *, const struct dpif_sflow *, - const struct dpif_ipfix *, const struct netflow *, + const struct mbridge *, const struct dpif_elephant *, + const struct dpif_sflow *, const struct dpif_ipfix *, + const struct netflow *, enum ofp_config_flags, bool forward_bpdu, bool has_in_band, bool enable_recirc, bool variable_length_userdata, diff --git a/ofproto/ofproto-dpif.c b/ofproto/ofproto-dpif.c index 980b04f17..d27607df9 100644 --- a/ofproto/ofproto-dpif.c +++ b/ofproto/ofproto-dpif.c @@ -51,6 +51,7 @@ #include "ofp-actions.h" #include "ofp-parse.h" #include "ofp-print.h" +#include "ofproto-dpif-elephant.h" #include "ofproto-dpif-ipfix.h" #include "ofproto-dpif-mirror.h" #include "ofproto-dpif-monitor.h" @@ -293,6 +294,7 @@ struct ofproto_dpif { bool has_bonded_bundles; bool lacp_enabled; struct mbridge *mbridge; + struct dpif_elephant *elephant; struct ovs_mutex stats_mutex; struct netdev_stats stats OVS_GUARDED; /* To account packets generated and @@ -596,6 +598,7 @@ type_run(const char *type) ofproto->backer->dpif, ofproto->miss_rule, ofproto->no_packet_in_rule, ofproto->ml, ofproto->stp, ofproto->ms, ofproto->mbridge, + ofproto->elephant, ofproto->sflow, ofproto->ipfix, ofproto->netflow, ofproto->up.frag_handling, ofproto->up.forward_bpdu, @@ -1133,6 +1136,7 @@ construct(struct ofproto *ofproto_) ofproto->sflow = NULL; ofproto->ipfix = NULL; ofproto->stp = NULL; + ofproto->elephant = NULL; ofproto->dump_seq = 0; hmap_init(&ofproto->bundles); ofproto->ml = mac_learning_create(MAC_ENTRY_DEFAULT_IDLE_TIME); @@ -3807,6 +3811,41 @@ packet_out(struct ofproto *ofproto_, struct ofpbuf *packet, ofpacts_len, packet); return 0; } + +/* Elephants. */ + +static int +set_elephant(struct ofproto *ofproto_, uint64_t mech, uint64_t arg1, + uint64_t arg2, int dscp) +{ + struct ofproto_dpif *ofproto = ofproto_dpif_cast(ofproto_); + struct dpif_elephant *de = ofproto->elephant; + + if (mech && !de) { + de = ofproto->elephant = dpif_elephant_create(); + } + + if (de) { + dpif_elephant_set_options(de, mech, arg1, arg2, dscp); + + if (!mech) { + dpif_elephant_unref(de); + ofproto->elephant = NULL; + } + } + + return 0; +} + +static int +get_elephants(struct ofproto *ofproto_ OVS_UNUSED, struct smap *elephants) +{ + smap_init(elephants); + + /* xxx Figure out how to do this. */ + + return 0; +} /* NetFlow. */ @@ -5100,6 +5139,8 @@ const struct ofproto_class ofproto_dpif_class = { rule_modify_actions, set_frag_handling, packet_out, + set_elephant, + get_elephants, set_netflow, get_netflow_ids, set_sflow, diff --git a/ofproto/ofproto-dpif.h b/ofproto/ofproto-dpif.h index 2f150b5e1..3a0c11d51 100644 --- a/ofproto/ofproto-dpif.h +++ b/ofproto/ofproto-dpif.h @@ -157,6 +157,8 @@ struct rule_dpif *ofproto_dpif_refresh_rule(struct rule_dpif *); struct ofport_dpif *odp_port_to_ofport(const struct dpif_backer *, odp_port_t); +int ofproto_get_elephant_dscp(struct ofproto_dpif *); + /* * Recirculation * ============= diff --git a/ofproto/ofproto-provider.h b/ofproto/ofproto-provider.h index 7e6e99bcf..f2ff2c5aa 100644 --- a/ofproto/ofproto-provider.h +++ b/ofproto/ofproto-provider.h @@ -1301,6 +1301,20 @@ struct ofproto_class { const struct ofpact *ofpacts, size_t ofpacts_len); + /* xxx Update this explanation. */ + + /* Configure detecting and handling of elephant flows. A flow is + * considered an elephant when it reaches 'bytes' for 'msecs' + * milliseconds. Once a flow is determined to be an elephant, it is + * never considered a mouse again. If 'dscp' is not -1, then that + * value will be used for the DSCP of packets placed on the wire. */ + int (*set_elephant)(struct ofproto *ofproto, uint64_t mech, + uint64_t arg1, uint64_t arg2, int dscp); + + /* Populates "elephants" with the key a string representation of the + * flow and the value with the byte count. */ + int (*get_elephants)(struct ofproto *ofproto, struct smap *elephants); + /* ## ------------------------- ## */ /* ## OFPP_NORMAL configuration ## */ /* ## ------------------------- ## */ diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index fca7d09e7..072da32fd 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -780,6 +780,25 @@ ofproto_set_snoops(struct ofproto *ofproto, const struct sset *snoops) return connmgr_set_snoops(ofproto->connmgr, snoops); } +/* xxx Move to better location and explain. */ +int +ofproto_set_elephant(struct ofproto *ofproto, uint64_t mech, + uint64_t arg1, uint64_t arg2, int dscp) +{ + return (ofproto->ofproto_class->set_elephant + ? ofproto->ofproto_class->set_elephant(ofproto, mech, arg1, + arg2, dscp) + : EOPNOTSUPP); +} + +int +ofproto_get_elephants(struct ofproto *ofproto, struct smap *elephants) +{ + return (ofproto->ofproto_class->get_elephants + ? ofproto->ofproto_class->get_elephants(ofproto, elephants) + : EOPNOTSUPP); +} + int ofproto_set_netflow(struct ofproto *ofproto, const struct netflow_options *nf_options) diff --git a/ofproto/ofproto.h b/ofproto/ofproto.h index c71662ebf..39c5ce653 100644 --- a/ofproto/ofproto.h +++ b/ofproto/ofproto.h @@ -256,6 +256,9 @@ int ofproto_port_set_mcast_snooping(struct ofproto *ofproto, void *aux, void ofproto_set_threads(int n_handlers, int n_revalidators); void ofproto_set_dp_desc(struct ofproto *, const char *dp_desc); int ofproto_set_snoops(struct ofproto *, const struct sset *snoops); +int ofproto_set_elephant(struct ofproto *, uint64_t mech, uint64_t arg1, + uint64_t arg2, int dscp); +int ofproto_get_elephants(struct ofproto *, struct smap *elephants); int ofproto_set_netflow(struct ofproto *, const struct netflow_options *nf_options); int ofproto_set_sflow(struct ofproto *, const struct ofproto_sflow_options *); |