struct mbridge *mbridge; /* Mirroring. */
struct dpif_sflow *sflow; /* SFlow handle, or null. */
struct dpif_ipfix *ipfix; /* Ipfix handle, or null. */
+ struct netflow *netflow; /* Netflow handle, or null. */
struct stp *stp; /* STP or null if disabled. */
/* Special rules installed by ofproto-dpif. */
struct rule_dpif *no_packet_in_rule;
enum ofp_config_flags frag; /* Fragmentation handling. */
- bool has_netflow; /* Bridge runs netflow? */
bool has_in_band; /* Bridge has in band control? */
bool forward_bpdu; /* Bridge forwards STP BPDUs? */
};
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,
- uint8_t table_id, bool may_packet_in);
+ 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,
+ uint8_t table_id, bool may_packet_in);
static bool input_vid_is_valid(uint16_t vid, struct xbundle *, bool warn);
static uint16_t input_vid_to_vlan(const struct xbundle *, uint16_t vid);
static void output_normal(struct xlate_ctx *, const struct xbundle *,
const struct mac_learning *ml, struct stp *stp,
const struct mbridge *mbridge,
const struct dpif_sflow *sflow,
- const struct dpif_ipfix *ipfix, enum ofp_config_flags frag,
- bool forward_bpdu, bool has_in_band, bool has_netflow)
+ const struct dpif_ipfix *ipfix,
+ const struct netflow *netflow, enum ofp_config_flags frag,
+ bool forward_bpdu, bool has_in_band)
{
struct xbridge *xbridge = xbridge_lookup(ofproto);
xbridge->stp = stp_ref(stp);
}
+ if (xbridge->netflow != netflow) {
+ netflow_unref(xbridge->netflow);
+ xbridge->netflow = netflow_ref(netflow);
+ }
+
free(xbridge->name);
xbridge->name = xstrdup(name);
xbridge->dpif = dpif;
xbridge->forward_bpdu = forward_bpdu;
xbridge->has_in_band = has_in_band;
- xbridge->has_netflow = has_netflow;
xbridge->frag = frag;
xbridge->miss_rule = miss_rule;
xbridge->no_packet_in_rule = no_packet_in_rule;
* respectively), populates 'flow' with the result of odp_flow_key_to_flow().
* Optionally, if nonnull, populates 'fitnessp' with the fitness of 'flow' as
* returned by odp_flow_key_to_flow(). Also, optionally populates 'ofproto'
- * with the ofproto_dpif, and 'odp_in_port' with the datapath in_port, that
- * 'packet' ingressed.
+ * with the ofproto_dpif, 'odp_in_port' with the datapath in_port, that
+ * 'packet' ingressed, and 'ipfix', 'sflow', and 'netflow' with the appropriate
+ * handles for those protocols if they're enabled. Caller is responsible for
+ * unrefing them.
*
* If 'ofproto' is nonnull, requires 'flow''s in_port to exist. Otherwise sets
* 'flow''s in_port to OFPP_NONE.
xlate_receive(const struct dpif_backer *backer, struct ofpbuf *packet,
const struct nlattr *key, size_t key_len,
struct flow *flow, enum odp_key_fitness *fitnessp,
- struct ofproto_dpif **ofproto, odp_port_t *odp_in_port)
+ struct ofproto_dpif **ofproto, struct dpif_ipfix **ipfix,
+ struct dpif_sflow **sflow, struct netflow **netflow,
+ odp_port_t *odp_in_port)
{
enum odp_key_fitness fitness;
const struct xport *xport;
}
xport = xport_lookup(tnl_port_should_receive(flow)
- ? tnl_port_receive(flow)
- : odp_port_to_ofport(backer, flow->in_port.odp_port));
+ ? tnl_port_receive(flow)
+ : odp_port_to_ofport(backer, flow->in_port.odp_port));
flow->in_port.ofp_port = xport ? xport->ofp_port : OFPP_NONE;
if (!xport) {
*ofproto = xport->xbridge->ofproto;
}
+ if (ipfix) {
+ *ipfix = dpif_ipfix_ref(xport->xbridge->ipfix);
+ }
+
+ if (sflow) {
+ *sflow = dpif_sflow_ref(xport->xbridge->sflow);
+ }
+
+ if (netflow) {
+ *netflow = netflow_ref(xport->xbridge->netflow);
+ }
+
exit:
if (fitnessp) {
*fitnessp = fitness;
}
return !ofputil_bucket_has_liveness(bucket) ||
- (bucket->watch_port != OFPP_ANY &&
- odp_port_is_alive(ctx, bucket->watch_port)) ||
- (bucket->watch_group != OFPG_ANY &&
- group_is_alive(ctx, bucket->watch_group, depth + 1));
+ (bucket->watch_port != OFPP_ANY &&
+ odp_port_is_alive(ctx, bucket->watch_port)) ||
+ (bucket->watch_group != OFPG_ANY &&
+ group_is_alive(ctx, bucket->watch_group, depth + 1));
}
static const struct ofputil_bucket *
/* No slaves enabled, so drop packet. */
return;
}
+
+ if (ctx->xin->resubmit_stats) {
+ bond_account(out_xbundle->bond, &ctx->xin->flow, vid,
+ ctx->xin->resubmit_stats->n_bytes);
+ }
}
old_tci = *flow_tci;
const struct flow *flow,
struct flow_wildcards *wc,
int vlan, struct xbundle *in_xbundle)
- OVS_REQ_RDLOCK(ml->rwlock)
+OVS_REQ_RDLOCK(ml->rwlock)
{
struct mac_entry *mac;
update_learning_table__(const struct xbridge *xbridge,
const struct flow *flow, struct flow_wildcards *wc,
int vlan, struct xbundle *in_xbundle)
- OVS_REQ_WRLOCK(xbridge->ml->rwlock)
+OVS_REQ_WRLOCK(xbridge->ml->rwlock)
{
struct mac_entry *mac;
|| mac_entry_is_grat_arp_locked(mac))) {
ovs_rwlock_unlock(&xbridge->ml->rwlock);
xlate_report(ctx, "SLB bond thinks this packet looped back, "
- "dropping");
+ "dropping");
return false;
}
ovs_rwlock_unlock(&xbridge->ml->rwlock);
if (ctx->xin->resubmit_stats) {
netdev_vport_inc_tx(xport->netdev, ctx->xin->resubmit_stats);
netdev_vport_inc_rx(peer->netdev, ctx->xin->resubmit_stats);
+ if (peer->bfd) {
+ bfd_account_rx(peer->bfd, ctx->xin->resubmit_stats);
+ }
}
return;
/* XXX
* check if table configuration flags
- * OFPTC_TABLE_MISS_CONTROLLER, default.
- * OFPTC_TABLE_MISS_CONTINUE,
- * OFPTC_TABLE_MISS_DROP
- * When OF1.0, OFPTC_TABLE_MISS_CONTINUE is used. What to do? */
+ * OFPTC11_TABLE_MISS_CONTROLLER, default.
+ * OFPTC11_TABLE_MISS_CONTINUE,
+ * OFPTC11_TABLE_MISS_DROP
+ * When OF1.0, OFPTC11_TABLE_MISS_CONTINUE is used. What to do? */
xport = get_ofp_port(ctx->xbridge, ctx->xin->flow.in_port.ofp_port);
choose_miss_rule(xport ? xport->config : 0,
ctx->xbridge->miss_rule,
ofpbuf_put(&dst->odp_actions, src->odp_actions.data,
src->odp_actions.size);
}
-
-/* Returns a reference to the sflow handled associated with ofproto, or NULL if
- * there is none. The caller is responsible for decrementing the results ref
- * count with dpif_sflow_unref(). */
-struct dpif_sflow *
-xlate_get_sflow(const struct ofproto_dpif *ofproto)
-{
- struct dpif_sflow *sflow = NULL;
- struct xbridge *xbridge;
-
- ovs_rwlock_rdlock(&xlate_rwlock);
- xbridge = xbridge_lookup(ofproto);
- if (xbridge) {
- sflow = dpif_sflow_ref(xbridge->sflow);
- }
- ovs_rwlock_unlock(&xlate_rwlock);
-
- return sflow;
-}
-
-/* Returns a reference to the ipfix handled associated with ofproto, or NULL if
- * there is none. The caller is responsible for decrementing the results ref
- * count with dpif_ipfix_unref(). */
-struct dpif_ipfix *
-xlate_get_ipfix(const struct ofproto_dpif *ofproto)
-{
- struct dpif_ipfix *ipfix = NULL;
- struct xbridge *xbridge;
-
- ovs_rwlock_rdlock(&xlate_rwlock);
- xbridge = xbridge_lookup(ofproto);
- if (xbridge) {
- ipfix = dpif_ipfix_ref(xbridge->ipfix);
- }
- ovs_rwlock_unlock(&xlate_rwlock);
-
- return ipfix;
-}
\f
static struct skb_priority_to_dscp *
get_skb_priority(const struct xport *xport, uint32_t skb_priority)
wc->masks.nw_frag |= FLOW_NW_FRAG_MASK;
tnl_may_send = tnl_xlate_init(&ctx.base_flow, flow, wc);
- if (ctx.xbridge->has_netflow) {
+ if (ctx.xbridge->netflow) {
netflow_mask_wc(flow, wc);
}
}
in_port = get_ofp_port(ctx.xbridge, flow->in_port.ofp_port);
+ if (in_port && in_port->is_tunnel && ctx.xin->resubmit_stats) {
+ netdev_vport_inc_rx(in_port->netdev, ctx.xin->resubmit_stats);
+ if (in_port->bfd) {
+ bfd_account_rx(in_port->bfd, ctx.xin->resubmit_stats);
+ }
+ }
+
special = process_special(&ctx, flow, in_port, ctx.xin->packet);
if (special) {
ctx.xout->slow |= special;
ctx.xout->slow |= SLOW_ACTION;
}
+ if (ctx.xin->resubmit_stats) {
+ mirror_update_stats(ctx.xbridge->mbridge, xout->mirrors,
+ ctx.xin->resubmit_stats->n_packets,
+ ctx.xin->resubmit_stats->n_bytes);
+
+ if (ctx.xbridge->netflow) {
+ const struct ofpact *ofpacts;
+ size_t ofpacts_len;
+
+ ofpacts_len = actions->ofpacts_len;
+ ofpacts = actions->ofpacts;
+ if (ofpacts_len == 0
+ || ofpacts->type != OFPACT_CONTROLLER
+ || ofpact_next(ofpacts) < ofpact_end(ofpacts, ofpacts_len)) {
+ /* Only update netflow if we don't have controller flow. We don't
+ * report NetFlow expiration messages for such facets because they
+ * are just part of the control logic for the network, not real
+ * traffic. */
+ netflow_flow_update(ctx.xbridge->netflow, flow,
+ xout->nf_output_iface,
+ ctx.xin->resubmit_stats);
+ }
+ }
+ }
+
ofpbuf_uninit(&ctx.stack);
ofpbuf_uninit(&ctx.action_set);
/* Clear the metadata and register wildcard masks, because we won't
* use non-header fields as part of the cache. */
- memset(&wc->masks.metadata, 0, sizeof wc->masks.metadata);
- memset(&wc->masks.regs, 0, sizeof wc->masks.regs);
+ flow_wildcards_clear_non_packet_fields(wc);
out:
rule_actions_unref(actions);