/* Maximum depth of flow table recursion (due to resubmit actions) in a
* flow translation. */
-#define MAX_RESUBMIT_RECURSION 32
+#define MAX_RESUBMIT_RECURSION 64
/* Number of implemented OpenFlow tables. */
enum { N_TABLES = 255 };
return ofport->cfm ? cfm_get_fault(ofport->cfm) : -1;
}
+static int
+get_cfm_opup(const struct ofport *ofport_)
+{
+ struct ofport_dpif *ofport = ofport_dpif_cast(ofport_);
+
+ return ofport->cfm ? cfm_get_opup(ofport->cfm) : -1;
+}
+
static int
get_cfm_remote_mpids(const struct ofport *ofport_, const uint64_t **rmps,
size_t *n_rmps)
break;
case PORT_VLAN_TRUNK:
- trunks = (unsigned long *) s->trunks;
+ trunks = CONST_CAST(unsigned long *, s->trunks);
break;
case PORT_VLAN_NATIVE_UNTAGGED:
bitmap_set1(trunks, vlan);
bitmap_set0(trunks, 0);
} else {
- trunks = (unsigned long *) s->trunks;
+ trunks = CONST_CAST(unsigned long *, s->trunks);
}
break;
port_run_fast(ofport);
if (ofport->cfm) {
+ int cfm_opup = cfm_get_opup(ofport->cfm);
+
cfm_run(ofport->cfm);
- enable = enable && !cfm_get_fault(ofport->cfm)
- && cfm_get_opup(ofport->cfm);
+ enable = enable && !cfm_get_fault(ofport->cfm);
+
+ if (cfm_opup >= 0) {
+ enable = enable && cfm_opup;
+ }
}
if (ofport->bundle) {
/* ofproto->stats.rx_packets represents packets that were received on
* some port and we processed internally and dropped (e.g. STP).
- * Account fro them as if they had been forwarded to OFPP_LOCAL. */
+ * Account for them as if they had been forwarded to OFPP_LOCAL. */
if (stats->tx_packets != UINT64_MAX) {
stats->tx_packets += ofproto->stats.rx_packets;
flow_get_metadata(flow, &pin.fmd);
- /* Registers aren't meaningful on a miss. */
- memset(pin.fmd.reg_masks, 0, sizeof pin.fmd.reg_masks);
-
connmgr_send_packet_in(ofproto->up.connmgr, &pin);
}
const struct ofpact *ofpacts = rule->ofpacts;
size_t ofpacts_len = rule->ofpacts_len;
- if (ofpacts->type == OFPACT_CONTROLLER &&
+ if (ofpacts_len > 0 &&
+ ofpacts->type == OFPACT_CONTROLLER &&
ofpact_next(ofpacts) >= ofpact_end(ofpacts, ofpacts_len)) {
return true;
}
uint32_t key_hash = odp_flow_key_hash(key, key_len);
struct subfacet *subfacet;
- subfacet = subfacet_find__(ofproto, key, key_len, key_hash, &facet->flow);
- if (subfacet) {
- if (subfacet->facet == facet) {
- return subfacet;
+ if (list_is_empty(&facet->subfacets)) {
+ subfacet = &facet->one_subfacet;
+
+ /* This subfacet should conceptually be created, and have its first
+ * packet pass through, at the same time that its facet was created.
+ * If we called time_msec() here, then the subfacet could look
+ * (occasionally) as though it was used some time after the facet was
+ * used. That can make a one-packet flow look like it has a nonzero
+ * duration, which looks odd in e.g. NetFlow statistics. */
+ subfacet->used = facet->used;
+ } else {
+ subfacet = subfacet_find__(ofproto, key, key_len, key_hash,
+ &facet->flow);
+ if (subfacet) {
+ if (subfacet->facet == facet) {
+ return subfacet;
+ }
+
+ /* This shouldn't happen. */
+ VLOG_ERR_RL(&rl, "subfacet with wrong facet");
+ subfacet_destroy(subfacet);
}
- /* This shouldn't happen. */
- VLOG_ERR_RL(&rl, "subfacet with wrong facet");
- subfacet_destroy(subfacet);
+ subfacet = xmalloc(sizeof *subfacet);
+ subfacet->used = time_msec();
}
- subfacet = (list_is_empty(&facet->subfacets)
- ? &facet->one_subfacet
- : xmalloc(sizeof *subfacet));
hmap_insert(&ofproto->subfacets, &subfacet->hmap_node, key_hash);
list_push_back(&facet->subfacets, &subfacet->list_node);
subfacet->facet = facet;
subfacet->key = NULL;
subfacet->key_len = 0;
}
- subfacet->used = time_msec();
subfacet->dp_packet_count = 0;
subfacet->dp_byte_count = 0;
subfacet->actions_len = 0;
struct flow flow;
int error;
- flow_extract((struct ofpbuf *) packet, 0, 0, 0, &flow);
+ flow_extract(packet, 0, 0, 0, &flow);
odp_port = vsp_realdev_to_vlandev(ofproto, ofport->odp_port,
flow.vlan_tci);
if (odp_port != ofport->odp_port) {
}
static bool
-compose_dec_ttl(struct action_xlate_ctx *ctx)
+compose_dec_ttl(struct action_xlate_ctx *ctx, struct ofpact_cnt_ids *ids)
{
if (ctx->flow.dl_type != htons(ETH_TYPE_IP) &&
ctx->flow.dl_type != htons(ETH_TYPE_IPV6)) {
ctx->flow.nw_ttl--;
return false;
} else {
- execute_controller_action(ctx, UINT16_MAX, OFPR_INVALID_TTL, 0);
+ size_t i;
+
+ for (i = 0; i < ids->n_controllers; i++) {
+ execute_controller_action(ctx, UINT16_MAX, OFPR_INVALID_TTL,
+ ids->cnt_ids[i]);
+ }
/* Stop processing for current table. */
return true;
break;
case OFPACT_DEC_TTL:
- if (compose_dec_ttl(ctx)) {
+ if (compose_dec_ttl(ctx, ofpact_get_DEC_TTL(a))) {
goto out;
}
break;
set_sflow,
set_cfm,
get_cfm_fault,
+ get_cfm_opup,
get_cfm_remote_mpids,
get_cfm_health,
set_stp,