static void stp_run(struct ofproto_dpif *ofproto);
static void stp_wait(struct ofproto_dpif *ofproto);
+static int set_stp_port(struct ofport *,
+ const struct ofproto_port_stp_settings *);
static bool ofbundle_includes_vlan(const struct ofbundle *, uint16_t vlan);
bool *arp_match_ip, uint32_t *actions)
{
*arp_match_ip = true;
- *actions = ((1u << OFPAT_OUTPUT) |
- (1u << OFPAT_SET_VLAN_VID) |
- (1u << OFPAT_SET_VLAN_PCP) |
- (1u << OFPAT_STRIP_VLAN) |
- (1u << OFPAT_SET_DL_SRC) |
- (1u << OFPAT_SET_DL_DST) |
- (1u << OFPAT_SET_NW_SRC) |
- (1u << OFPAT_SET_NW_DST) |
- (1u << OFPAT_SET_NW_TOS) |
- (1u << OFPAT_SET_TP_SRC) |
- (1u << OFPAT_SET_TP_DST) |
- (1u << OFPAT_ENQUEUE));
+ *actions = ((1u << OFPAT10_OUTPUT) |
+ (1u << OFPAT10_SET_VLAN_VID) |
+ (1u << OFPAT10_SET_VLAN_PCP) |
+ (1u << OFPAT10_STRIP_VLAN) |
+ (1u << OFPAT10_SET_DL_SRC) |
+ (1u << OFPAT10_SET_DL_DST) |
+ (1u << OFPAT10_SET_NW_SRC) |
+ (1u << OFPAT10_SET_NW_DST) |
+ (1u << OFPAT10_SET_NW_TOS) |
+ (1u << OFPAT10_SET_TP_SRC) |
+ (1u << OFPAT10_SET_TP_DST) |
+ (1u << OFPAT10_ENQUEUE));
}
static void
stp_set_max_age(ofproto->stp, s->max_age);
stp_set_forward_delay(ofproto->stp, s->fwd_delay);
} else {
+ struct ofport *ofport;
+
+ HMAP_FOR_EACH (ofport, hmap_node, &ofproto->up.ports) {
+ set_stp_port(ofport, NULL);
+ }
+
stp_destroy(ofproto->stp);
ofproto->stp = NULL;
}
pin.packet_len = packet->size;
pin.total_len = packet->size;
pin.reason = OFPR_NO_MATCH;
+ pin.controller_id = 0;
pin.table_id = 0;
pin.cookie = 0;
if (rule->up.hard_timeout
&& now > rule->up.modified + rule->up.hard_timeout * 1000) {
reason = OFPRR_HARD_TIMEOUT;
- } else if (rule->up.idle_timeout && list_is_empty(&rule->facets)
+ } else if (rule->up.idle_timeout
&& now > rule->up.used + rule->up.idle_timeout * 1000) {
reason = OFPRR_IDLE_TIMEOUT;
} else {
static void
execute_controller_action(struct action_xlate_ctx *ctx, int len,
- enum ofp_packet_in_reason reason)
+ enum ofp_packet_in_reason reason,
+ uint16_t controller_id)
{
struct ofputil_packet_in pin;
struct ofpbuf *packet;
pin.packet = packet->data;
pin.packet_len = packet->size;
pin.reason = reason;
+ pin.controller_id = controller_id;
pin.table_id = ctx->table_id;
pin.cookie = ctx->rule ? ctx->rule->up.flow_cookie : 0;
ctx->flow.nw_ttl--;
return false;
} else {
- execute_controller_action(ctx, UINT16_MAX, OFPR_INVALID_TTL);
+ execute_controller_action(ctx, UINT16_MAX, OFPR_INVALID_TTL, 0);
/* Stop processing for current table. */
return true;
flood_packets(ctx, true);
break;
case OFPP_CONTROLLER:
- execute_controller_action(ctx, max_len, OFPR_ACTION);
+ execute_controller_action(ctx, max_len, OFPR_ACTION, 0);
break;
case OFPP_NONE:
break;
const struct nx_action_autopath *naa;
const struct nx_action_bundle *nab;
const struct nx_action_output_reg *naor;
+ const struct nx_action_controller *nac;
enum ofputil_action_code code;
ovs_be64 tun_id;
code = ofputil_decode_action_unsafe(ia);
switch (code) {
- case OFPUTIL_OFPAT_OUTPUT:
+ case OFPUTIL_OFPAT10_OUTPUT:
xlate_output_action(ctx, &ia->output);
break;
- case OFPUTIL_OFPAT_SET_VLAN_VID:
+ case OFPUTIL_OFPAT10_SET_VLAN_VID:
ctx->flow.vlan_tci &= ~htons(VLAN_VID_MASK);
ctx->flow.vlan_tci |= ia->vlan_vid.vlan_vid | htons(VLAN_CFI);
break;
- case OFPUTIL_OFPAT_SET_VLAN_PCP:
+ case OFPUTIL_OFPAT10_SET_VLAN_PCP:
ctx->flow.vlan_tci &= ~htons(VLAN_PCP_MASK);
ctx->flow.vlan_tci |= htons(
(ia->vlan_pcp.vlan_pcp << VLAN_PCP_SHIFT) | VLAN_CFI);
break;
- case OFPUTIL_OFPAT_STRIP_VLAN:
+ case OFPUTIL_OFPAT10_STRIP_VLAN:
ctx->flow.vlan_tci = htons(0);
break;
- case OFPUTIL_OFPAT_SET_DL_SRC:
+ case OFPUTIL_OFPAT10_SET_DL_SRC:
oada = ((struct ofp_action_dl_addr *) ia);
memcpy(ctx->flow.dl_src, oada->dl_addr, ETH_ADDR_LEN);
break;
- case OFPUTIL_OFPAT_SET_DL_DST:
+ case OFPUTIL_OFPAT10_SET_DL_DST:
oada = ((struct ofp_action_dl_addr *) ia);
memcpy(ctx->flow.dl_dst, oada->dl_addr, ETH_ADDR_LEN);
break;
- case OFPUTIL_OFPAT_SET_NW_SRC:
+ case OFPUTIL_OFPAT10_SET_NW_SRC:
ctx->flow.nw_src = ia->nw_addr.nw_addr;
break;
- case OFPUTIL_OFPAT_SET_NW_DST:
+ case OFPUTIL_OFPAT10_SET_NW_DST:
ctx->flow.nw_dst = ia->nw_addr.nw_addr;
break;
- case OFPUTIL_OFPAT_SET_NW_TOS:
+ case OFPUTIL_OFPAT10_SET_NW_TOS:
/* OpenFlow 1.0 only supports IPv4. */
if (ctx->flow.dl_type == htons(ETH_TYPE_IP)) {
ctx->flow.nw_tos &= ~IP_DSCP_MASK;
}
break;
- case OFPUTIL_OFPAT_SET_TP_SRC:
+ case OFPUTIL_OFPAT10_SET_TP_SRC:
ctx->flow.tp_src = ia->tp_port.tp_port;
break;
- case OFPUTIL_OFPAT_SET_TP_DST:
+ case OFPUTIL_OFPAT10_SET_TP_DST:
ctx->flow.tp_dst = ia->tp_port.tp_port;
break;
- case OFPUTIL_OFPAT_ENQUEUE:
+ case OFPUTIL_OFPAT10_ENQUEUE:
xlate_enqueue_action(ctx, (const struct ofp_action_enqueue *) ia);
break;
ctx->has_fin_timeout = true;
xlate_fin_timeout(ctx, (const struct nx_action_fin_timeout *) ia);
break;
+
+ case OFPUTIL_NXAST_CONTROLLER:
+ nac = (const struct nx_action_controller *) ia;
+ execute_controller_action(ctx, ntohs(nac->max_len), nac->reason,
+ ntohs(nac->controller_id));
+ break;
}
}
if (argc > 1) {
ofproto = ofproto_dpif_lookup(argv[1]);
if (!ofproto) {
- unixctl_command_reply(conn, 501, "no such bridge");
+ unixctl_command_reply_error(conn, "no such bridge");
return;
}
mac_learning_flush(ofproto->ml, &ofproto->revalidate_set);
}
}
- unixctl_command_reply(conn, 200, "table successfully flushed");
+ unixctl_command_reply(conn, "table successfully flushed");
}
static void
ofproto = ofproto_dpif_lookup(argv[1]);
if (!ofproto) {
- unixctl_command_reply(conn, 501, "no such bridge");
+ unixctl_command_reply_error(conn, "no such bridge");
return;
}
e->vlan, ETH_ADDR_ARGS(e->mac),
mac_entry_age(ofproto->ml, e));
}
- unixctl_command_reply(conn, 200, ds_cstr(&ds));
+ unixctl_command_reply(conn, ds_cstr(&ds));
ds_destroy(&ds);
}
ds_put_char(result, '\n');
}
+static void
+trace_format_odp(struct ds *result, int level, const char *title,
+ struct ofproto_trace *trace)
+{
+ struct ofpbuf *odp_actions = trace->ctx.odp_actions;
+
+ ds_put_char_multiple(result, '\t', level);
+ ds_put_format(result, "%s: ", title);
+ format_odp_actions(result, odp_actions->data, odp_actions->size);
+ ds_put_char(result, '\n');
+}
+
static void
trace_resubmit(struct action_xlate_ctx *ctx, struct rule_dpif *rule)
{
ds_put_char(result, '\n');
trace_format_flow(result, ctx->recurse + 1, "Resubmitted flow", trace);
trace_format_regs(result, ctx->recurse + 1, "Resubmitted regs", trace);
+ trace_format_odp(result, ctx->recurse + 1, "Resubmitted odp", trace);
trace_format_rule(result, ctx->table_id, ctx->recurse + 1, rule);
}
ofproto = ofproto_dpif_lookup(dpname);
if (!ofproto) {
- unixctl_command_reply(conn, 501, "Unknown ofproto (use ofproto/list "
- "for help)");
+ unixctl_command_reply_error(conn, "Unknown ofproto (use ofproto/list "
+ "for help)");
goto exit;
}
if (argc == 3 || (argc == 4 && !strcmp(argv[3], "-generate"))) {
ofpbuf_init(&odp_key, 0);
error = odp_flow_key_from_string(flow_s, NULL, &odp_key);
if (error) {
- unixctl_command_reply(conn, 501, "Bad flow syntax");
+ unixctl_command_reply_error(conn, "Bad flow syntax");
goto exit;
}
odp_key.size, &flow,
&initial_tci, NULL);
if (error == ODP_FIT_ERROR) {
- unixctl_command_reply(conn, 501, "Invalid flow");
+ unixctl_command_reply_error(conn, "Invalid flow");
goto exit;
}
msg = eth_from_hex(packet_s, &packet);
if (msg) {
- unixctl_command_reply(conn, 501, msg);
+ unixctl_command_reply_error(conn, msg);
goto exit;
}
flow_extract(packet, priority, tun_id, in_port, &flow);
initial_tci = flow.vlan_tci;
} else {
- unixctl_command_reply(conn, 501, "Bad command syntax");
+ unixctl_command_reply_error(conn, "Bad command syntax");
goto exit;
}
}
}
- unixctl_command_reply(conn, 200, ds_cstr(&result));
+ unixctl_command_reply(conn, ds_cstr(&result));
exit:
ds_destroy(&result);
const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
{
clogged = true;
- unixctl_command_reply(conn, 200, NULL);
+ unixctl_command_reply(conn, NULL);
}
static void
const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
{
clogged = false;
- unixctl_command_reply(conn, 200, NULL);
+ unixctl_command_reply(conn, NULL);
}
/* Runs a self-check of flow translations in 'ofproto'. Appends a message to
if (argc > 1) {
ofproto = ofproto_dpif_lookup(argv[1]);
if (!ofproto) {
- unixctl_command_reply(conn, 501, "Unknown ofproto (use "
- "ofproto/list for help)");
+ unixctl_command_reply_error(conn, "Unknown ofproto (use "
+ "ofproto/list for help)");
return;
}
ofproto_dpif_self_check__(ofproto, &reply);
}
}
- unixctl_command_reply(conn, 200, ds_cstr(&reply));
+ unixctl_command_reply(conn, ds_cstr(&reply));
ds_destroy(&reply);
}