summaryrefslogtreecommitdiff
path: root/ofproto
diff options
context:
space:
mode:
Diffstat (limited to 'ofproto')
-rw-r--r--ofproto/automake.mk2
-rw-r--r--ofproto/ofproto-dpif-elephant.c58
-rw-r--r--ofproto/ofproto-dpif-elephant.h40
-rw-r--r--ofproto/ofproto-dpif-xlate.c70
-rw-r--r--ofproto/ofproto-dpif-xlate.h6
-rw-r--r--ofproto/ofproto-dpif.c41
-rw-r--r--ofproto/ofproto-dpif.h2
-rw-r--r--ofproto/ofproto-provider.h14
-rw-r--r--ofproto/ofproto.c19
-rw-r--r--ofproto/ofproto.h3
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 *);