Before this patch, special packets such as LACP and CFM messages
were only processed if they had NORMAL open flow actions. With
this patch these messages are always processed unless originated in
ofproto_send_packet().
* calling action_xlate_ctx_init(). */
void (*resubmit_hook)(struct action_xlate_ctx *, const struct rule *);
* calling action_xlate_ctx_init(). */
void (*resubmit_hook)(struct action_xlate_ctx *, const struct rule *);
+ /* If true, the speciality of 'flow' should be checked before executing
+ * its actions. If special_cb returns false on 'flow' rendered
+ * uninstallable and no actions will be executed. */
+ bool check_special;
+
/* xlate_actions() initializes and uses these members. The client might want
* to look at them after it returns. */
/* xlate_actions() initializes and uses these members. The client might want
* to look at them after it returns. */
struct ofpbuf *odp_actions;
action_xlate_ctx_init(&ctx, p, flow, packet);
struct ofpbuf *odp_actions;
action_xlate_ctx_init(&ctx, p, flow, packet);
+ /* Always xlate packets originated in this function. */
+ ctx.check_special = false;
odp_actions = xlate_actions(&ctx, actions, n_actions);
/* XXX Should we translate the dpif_execute() errno value into an OpenFlow
odp_actions = xlate_actions(&ctx, actions, n_actions);
/* XXX Should we translate the dpif_execute() errno value into an OpenFlow
ctx->flow = *flow;
ctx->packet = packet;
ctx->resubmit_hook = NULL;
ctx->flow = *flow;
ctx->packet = packet;
ctx->resubmit_hook = NULL;
+ ctx->check_special = true;
ctx->nf_output_iface = NF_OUT_DROP;
ctx->recurse = 0;
ctx->last_pop_priority = -1;
ctx->nf_output_iface = NF_OUT_DROP;
ctx->recurse = 0;
ctx->last_pop_priority = -1;
- do_xlate_actions(in, n_in, ctx);
+
+ if (!ctx->check_special
+ || (ctx->ofproto->ofhooks->special_cb
+ && ctx->ofproto->ofhooks->special_cb(&ctx->flow, ctx->packet,
+ ctx->ofproto->aux))) {
+ do_xlate_actions(in, n_in, ctx);
+ } else {
+ ctx->may_set_up_flow = false;
+ }
+
remove_pop_action(ctx);
/* Check with in-band control to see if we're allowed to set up this
remove_pop_action(ctx);
/* Check with in-band control to see if we're allowed to set up this
/* Set header pointers in 'flow'. */
flow_extract(upcall->packet, flow.tun_id, flow.in_port, &flow);
/* Set header pointers in 'flow'. */
flow_extract(upcall->packet, flow.tun_id, flow.in_port, &flow);
+ if (p->ofhooks->special_cb
+ && !p->ofhooks->special_cb(&flow, upcall->packet, p->aux)) {
+ ofpbuf_delete(upcall->packet);
+ return;
+ }
+
/* Check with in-band control to see if this packet should be sent
* to the local port regardless of the flow table. */
if (in_band_msg_in_hook(p->in_band, &flow, upcall->packet)) {
/* Check with in-band control to see if this packet should be sent
* to the local port regardless of the flow table. */
if (in_band_msg_in_hook(p->in_band, &flow, upcall->packet)) {
static const struct ofhooks default_ofhooks = {
default_normal_ofhook_cb,
NULL,
static const struct ofhooks default_ofhooks = {
default_normal_ofhook_cb,
NULL,
bool (*normal_cb)(const struct flow *, const struct ofpbuf *packet,
struct ofpbuf *odp_actions, tag_type *,
uint16_t *nf_output_iface, void *aux);
bool (*normal_cb)(const struct flow *, const struct ofpbuf *packet,
struct ofpbuf *odp_actions, tag_type *,
uint16_t *nf_output_iface, void *aux);
+ bool (*special_cb)(const struct flow *flow, const struct ofpbuf *packet,
+ void *aux);
void (*account_flow_cb)(const struct flow *, tag_type tags,
const struct nlattr *odp_actions,
size_t actions_len,
void (*account_flow_cb)(const struct flow *, tag_type tags,
const struct nlattr *odp_actions,
size_t actions_len,
COVERAGE_DEFINE(bridge_flush);
COVERAGE_DEFINE(bridge_process_flow);
COVERAGE_DEFINE(bridge_flush);
COVERAGE_DEFINE(bridge_process_flow);
+COVERAGE_DEFINE(bridge_process_cfm);
+COVERAGE_DEFINE(bridge_process_lacp);
COVERAGE_DEFINE(bridge_reconfigure);
COVERAGE_DEFINE(bridge_lacp_update);
COVERAGE_DEFINE(bridge_reconfigure);
COVERAGE_DEFINE(bridge_lacp_update);
struct ofpbuf *actions, tag_type *tags,
uint16_t *nf_output_iface, void *br_)
{
struct ofpbuf *actions, tag_type *tags,
uint16_t *nf_output_iface, void *br_)
{
struct bridge *br = br_;
COVERAGE_INC(bridge_process_flow);
struct bridge *br = br_;
COVERAGE_INC(bridge_process_flow);
+ return process_flow(br, flow, packet, actions, tags, nf_output_iface);
+}
+
+static bool
+bridge_special_ofhook_cb(const struct flow *flow,
+ const struct ofpbuf *packet, void *br_)
+{
+ struct iface *iface;
+ struct bridge *br = br_;
iface = iface_from_dp_ifidx(br, flow->in_port);
if (cfm_should_process_flow(flow)) {
iface = iface_from_dp_ifidx(br, flow->in_port);
if (cfm_should_process_flow(flow)) {
- if (packet && iface->cfm) {
+
+ if (iface && packet && iface->cfm) {
+ COVERAGE_INC(bridge_process_cfm);
cfm_process_heartbeat(iface->cfm, packet);
}
return false;
} else if (flow->dl_type == htons(ETH_TYPE_LACP)) {
cfm_process_heartbeat(iface->cfm, packet);
}
return false;
} else if (flow->dl_type == htons(ETH_TYPE_LACP)) {
+
+ if (iface && packet) {
+ COVERAGE_INC(bridge_process_lacp);
lacp_process_packet(packet, iface);
}
return false;
}
lacp_process_packet(packet, iface);
}
return false;
}
- return process_flow(br, flow, packet, actions, tags, nf_output_iface);
static struct ofhooks bridge_ofhooks = {
bridge_normal_ofhook_cb,
static struct ofhooks bridge_ofhooks = {
bridge_normal_ofhook_cb,
+ bridge_special_ofhook_cb,
bridge_account_flow_ofhook_cb,
bridge_account_checkpoint_ofhook_cb,
};
bridge_account_flow_ofhook_cb,
bridge_account_checkpoint_ofhook_cb,
};