@@ -481,12 +481,14 @@ format_odp_userspace_action(struct ds *ds, const struct nlattr *attr,
} else if (cookie.type == USER_ACTION_COOKIE_CONTROLLER) {
ds_put_format(ds, ",controller(reason=%"PRIu16
",dont_send=%"PRIu8
+ ",continuation=%"PRIu8
",recirc_id=%"PRIu32
",rule_cookie=%#"PRIx64
",controller_id=%"PRIu16
",max_len=%"PRIu16,
cookie.controller.reason,
cookie.controller.dont_send ? 1 : 0,
+ cookie.controller.continuation ? 1 : 0,
cookie.controller.recirc_id,
ntohll(get_32aligned_be64(
&cookie.controller.rule_cookie)),
@@ -1146,6 +1148,7 @@ parse_odp_userspace_action(const char *s, struct ofpbuf *actions)
/* USER_ACTION_COOKIE_CONTROLLER. */
uint8_t dont_send;
+ uint8_t continuation;
uint16_t reason;
uint32_t recirc_id;
ovs_be64 rule_cookie;
@@ -1227,17 +1230,19 @@ parse_odp_userspace_action(const char *s, struct ofpbuf *actions)
cookie.ipfix.output_odp_port = u32_to_odp(output);
} else if (ovs_scan(&s[n], ",controller(reason=%"SCNu16
",dont_send=%"SCNu8
+ ",continuation=%"SCNu8
",recirc_id=%"SCNu32
",rule_cookie=%"SCNx64
",controller_id=%"SCNu16
",max_len=%"SCNu16")%n",
- &reason, &dont_send, &recirc_id, &rule_cookie,
- &controller_id, &max_len, &n1)) {
+ &reason, &dont_send, &continuation, &recirc_id,
+ &rule_cookie, &controller_id, &max_len, &n1)) {
n += n1;
cookie.type = USER_ACTION_COOKIE_CONTROLLER;
cookie.ofp_in_port = OFPP_NONE;
cookie.ofproto_uuid = UUID_ZERO;
cookie.controller.dont_send = dont_send ? true : false;
+ cookie.controller.continuation = continuation ? true : false;
cookie.controller.reason = reason;
cookie.controller.recirc_id = recirc_id;
put_32aligned_be64(&cookie.controller.rule_cookie,
@@ -43,7 +43,6 @@ struct pkt_metadata;
SPR(SLOW_LACP, "lacp", "Consists of LACP packets") \
SPR(SLOW_STP, "stp", "Consists of STP packets") \
SPR(SLOW_LLDP, "lldp", "Consists of LLDP packets") \
- SPR(SLOW_PAUSE, "pause", "Controller action with pause") \
SPR(SLOW_ACTION, "action", \
"Uses action(s) not supported by datapath")
@@ -337,6 +336,7 @@ struct user_action_cookie {
struct {
/* USER_ACTION_COOKIE_CONTROLLER. */
bool dont_send; /* Don't send the packet to controller. */
+ bool continuation; /* Send packet-in as a continuation. */
uint16_t reason;
uint32_t recirc_id;
ovs_32aligned_be64 rule_cookie;
@@ -1428,6 +1428,8 @@ process_upcall(struct udpif *udpif, struct upcall *upcall,
break;
}
+ const struct frozen_state *state = &recirc_node->state;
+
struct ofproto_async_msg *am = xmalloc(sizeof *am);
*am = (struct ofproto_async_msg) {
.controller_id = cookie->controller.controller_id,
@@ -1439,7 +1441,7 @@ process_upcall(struct udpif *udpif, struct upcall *upcall,
dp_packet_size(packet)),
.packet_len = dp_packet_size(packet),
.reason = cookie->controller.reason,
- .table_id = recirc_node->state.table_id,
+ .table_id = state->table_id,
.cookie = get_32aligned_be64(
&cookie->controller.rule_cookie),
.userdata = (recirc_node->state.userdata_len
@@ -1453,18 +1455,36 @@ process_upcall(struct udpif *udpif, struct upcall *upcall,
},
};
+ if (cookie->controller.continuation) {
+ am->pin.up.stack = (state->stack_size
+ ? xmemdup(state->stack, state->stack_size)
+ : NULL),
+ am->pin.up.stack_size = state->stack_size,
+ am->pin.up.mirrors = state->mirrors,
+ am->pin.up.conntracked = state->conntracked,
+ am->pin.up.actions = (state->ofpacts_len
+ ? xmemdup(state->ofpacts,
+ state->ofpacts_len) : NULL),
+ am->pin.up.actions_len = state->ofpacts_len,
+ am->pin.up.action_set = (state->action_set_len
+ ? xmemdup(state->action_set,
+ state->action_set_len)
+ : NULL),
+ am->pin.up.action_set_len = state->action_set_len,
+ am->pin.up.bridge = upcall->ofproto->uuid;
+ }
+
/* We don't want to use the upcall 'flow', since it may be
* more specific than the point at which the "controller"
* action was specified. */
struct flow frozen_flow;
frozen_flow = *flow;
- if (!recirc_node->state.conntracked) {
+ if (!state->conntracked) {
flow_clear_conntrack(&frozen_flow);
}
- frozen_metadata_to_flow(&recirc_node->state.metadata,
- &frozen_flow);
+ frozen_metadata_to_flow(&state->metadata, &frozen_flow);
flow_get_metadata(&frozen_flow, &am->pin.up.base.flow_metadata);
ofproto_dpif_send_async_msg(upcall->ofproto, am);
@@ -1494,9 +1514,6 @@ handle_upcalls(struct udpif *udpif, struct upcall *upcalls,
*
* - For SLOW_ACTION, translation executes the actions directly.
*
- * - For SLOW_PAUSE, translation needs to handle a pause request
- * from the controller.
- *
* The loop fills 'ops' with an array of operations to execute in the
* datapath. */
n_ops = 0;
@@ -154,13 +154,6 @@ xlate_push_stats_entry(struct xc_entry *entry,
tnl_neigh_lookup(entry->tnl_neigh_cache.br_name,
&entry->tnl_neigh_cache.d_ipv6, &dmac);
break;
- case XC_CONTROLLER:
- if (entry->controller.am) {
- ofproto_dpif_send_async_msg(entry->controller.ofproto,
- entry->controller.am);
- entry->controller.am = NULL; /* One time only. */
- }
- break;
case XC_TUNNEL_HEADER:
if (entry->tunnel_hdr.operation == ADD) {
stats->n_bytes += stats->n_packets * entry->tunnel_hdr.hdr_size;
@@ -248,12 +241,6 @@ xlate_cache_clear_entry(struct xc_entry *entry)
break;
case XC_TNL_NEIGH:
break;
- case XC_CONTROLLER:
- if (entry->controller.am) {
- ofproto_async_msg_free(entry->controller.am);
- entry->controller.am = NULL;
- }
- break;
case XC_TUNNEL_HEADER:
break;
default:
@@ -52,7 +52,6 @@ enum xc_type {
XC_FIN_TIMEOUT, /* Calls back to ofproto. */
XC_GROUP,
XC_TNL_NEIGH,
- XC_CONTROLLER,
XC_TUNNEL_HEADER,
};
@@ -365,7 +365,6 @@ struct xlate_ctx {
uint32_t dp_hash_basis;
struct ofpbuf frozen_actions;
const struct ofpact_controller *pause;
- struct flow *paused_flow;
/* True if a packet was but is no longer MPLS (due to an MPLS pop action).
* This is a trigger for recirculation in cases where translating an action
@@ -4356,6 +4355,35 @@ flood_packets(struct xlate_ctx *ctx, bool all, bool is_last_action)
}
static void
+put_controller_user_action(struct xlate_ctx *ctx,
+ bool dont_send, bool continuation,
+ uint32_t recirc_id, int len,
+ enum ofp_packet_in_reason reason,
+ uint16_t controller_id)
+{
+ struct user_action_cookie cookie;
+
+ memset(&cookie, 0, sizeof cookie);
+ cookie.type = USER_ACTION_COOKIE_CONTROLLER;
+ cookie.ofp_in_port = OFPP_NONE,
+ cookie.ofproto_uuid = ctx->xbridge->ofproto->uuid;
+ cookie.controller.dont_send = dont_send;
+ cookie.controller.continuation = continuation;
+ cookie.controller.reason = reason;
+ cookie.controller.recirc_id = recirc_id;
+ put_32aligned_be64(&cookie.controller.rule_cookie, ctx->rule_cookie);
+ cookie.controller.controller_id = controller_id;
+ cookie.controller.max_len = len;
+
+ odp_port_t odp_port = ofp_port_to_odp_port(ctx->xbridge,
+ ctx->xin->flow.in_port.ofp_port);
+ uint32_t pid = dpif_port_get_pid(ctx->xbridge->dpif, odp_port,
+ flow_hash_5tuple(&ctx->xin->flow, 0));
+ odp_put_userspace_action(pid, &cookie, sizeof cookie, ODPP_NONE,
+ false, ctx->odp_actions);
+}
+
+static void
xlate_controller_action(struct xlate_ctx *ctx, int len,
enum ofp_packet_in_reason reason,
uint16_t controller_id,
@@ -4409,31 +4437,14 @@ xlate_controller_action(struct xlate_ctx *ctx, int len,
nl_msg_put_u32(ctx->odp_actions, OVS_ACTION_ATTR_METER, meter_id);
}
- struct user_action_cookie cookie;
-
- memset(&cookie, 0, sizeof cookie);
- cookie.type = USER_ACTION_COOKIE_CONTROLLER;
- cookie.ofp_in_port = OFPP_NONE;
- cookie.ofproto_uuid = ctx->xbridge->ofproto->uuid;
- cookie.controller.dont_send = false;
- cookie.controller.reason = reason;
- cookie.controller.recirc_id = recirc_id;
- put_32aligned_be64(&cookie.controller.rule_cookie, ctx->rule_cookie);
- cookie.controller.max_len = len;
- cookie.controller.controller_id = controller_id;
-
/* Generate the datapath flows even if we don't send the packet-in
* so that debugging more closely represents normal state. */
+ bool dont_send = false;
if (!ctx->xin->allow_side_effects && !ctx->xin->xcache) {
- cookie.controller.dont_send = true;
+ dont_send = true;
}
-
- odp_port_t odp_port = ofp_port_to_odp_port(
- ctx->xbridge, ctx->xin->flow.in_port.ofp_port);
- uint32_t pid = dpif_port_get_pid(ctx->xbridge->dpif, odp_port,
- flow_hash_5tuple(&ctx->xin->flow, 0));
- odp_put_userspace_action(pid, &cookie, sizeof cookie, ODPP_NONE,
- false, ctx->odp_actions);
+ put_controller_user_action(ctx, dont_send, false, recirc_id, len,
+ reason, controller_id);
if (meter_id != UINT32_MAX) {
nl_msg_end_nested(ctx->odp_actions, ac_offset);
@@ -4441,57 +4452,6 @@ xlate_controller_action(struct xlate_ctx *ctx, int len,
}
}
-static void
-emit_continuation(struct xlate_ctx *ctx, const struct frozen_state *state)
-{
- if (!ctx->xin->allow_side_effects && !ctx->xin->xcache) {
- return;
- }
-
- struct ofproto_async_msg *am = xmalloc(sizeof *am);
- *am = (struct ofproto_async_msg) {
- .controller_id = ctx->pause->controller_id,
- .oam = OAM_PACKET_IN,
- .pin = {
- .up = {
- .base = {
- .userdata = xmemdup(ctx->pause->userdata,
- ctx->pause->userdata_len),
- .userdata_len = ctx->pause->userdata_len,
- .packet = xmemdup(dp_packet_data(ctx->xin->packet),
- dp_packet_size(ctx->xin->packet)),
- .packet_len = dp_packet_size(ctx->xin->packet),
- .reason = ctx->pause->reason,
- },
- .bridge = ctx->xbridge->ofproto->uuid,
- .stack = xmemdup(state->stack, state->stack_size),
- .stack_size = state->stack_size,
- .mirrors = state->mirrors,
- .conntracked = state->conntracked,
- .actions = xmemdup(state->ofpacts, state->ofpacts_len),
- .actions_len = state->ofpacts_len,
- .action_set = xmemdup(state->action_set,
- state->action_set_len),
- .action_set_len = state->action_set_len,
- },
- .max_len = UINT16_MAX,
- },
- };
- flow_get_metadata(ctx->paused_flow, &am->pin.up.base.flow_metadata);
-
- /* Async messages are only sent once, so if we send one now, no
- * xlate cache entry is created. */
- if (ctx->xin->allow_side_effects) {
- ofproto_dpif_send_async_msg(ctx->xbridge->ofproto, am);
- } else /* xcache */ {
- struct xc_entry *entry;
-
- entry = xlate_cache_add_entry(ctx->xin->xcache, XC_CONTROLLER);
- entry->controller.ofproto = ctx->xbridge->ofproto;
- entry->controller.am = am;
- }
-}
-
/* Creates a frozen state, and allocates a unique recirc id for the given
* state. Returns a non-zero recirc id if it is allocated successfully.
* Returns 0 otherwise.
@@ -4499,7 +4459,6 @@ emit_continuation(struct xlate_ctx *ctx, const struct frozen_state *state)
static uint32_t
finish_freezing__(struct xlate_ctx *ctx, uint8_t table)
{
- uint32_t id = 0;
ovs_assert(ctx->freezing);
struct frozen_state state = {
@@ -4513,27 +4472,35 @@ finish_freezing__(struct xlate_ctx *ctx, uint8_t table)
.ofpacts_len = ctx->frozen_actions.size,
.action_set = ctx->action_set.data,
.action_set_len = ctx->action_set.size,
+ .userdata = ctx->pause ? CONST_CAST(uint8_t *,ctx->pause->userdata)
+ : NULL,
+ .userdata_len = ctx->pause ? ctx->pause->userdata_len : 0,
};
frozen_metadata_from_flow(&state.metadata, &ctx->xin->flow);
+ /* Allocate a unique recirc id for the given metadata state in the
+ * flow. An existing id, with a new reference to the corresponding
+ * recirculation context, will be returned if possible.
+ * The life-cycle of this recirc id is managed by associating it
+ * with the udpif key ('ukey') created for each new datapath flow. */
+ uint32_t recirc_id = recirc_alloc_id_ctx(&state);
+ if (!recirc_id) {
+ xlate_report_error(ctx, "Failed to allocate recirculation id");
+ ctx->error = XLATE_NO_RECIRCULATION_CONTEXT;
+ return 0;
+ }
+ recirc_refs_add(&ctx->xout->recircs, recirc_id);
+
if (ctx->pause) {
- if (ctx->xin->packet) {
- emit_continuation(ctx, &state);
- }
- } else {
- /* Allocate a unique recirc id for the given metadata state in the
- * flow. An existing id, with a new reference to the corresponding
- * recirculation context, will be returned if possible.
- * The life-cycle of this recirc id is managed by associating it
- * with the udpif key ('ukey') created for each new datapath flow. */
- id = recirc_alloc_id_ctx(&state);
- if (!id) {
- xlate_report_error(ctx, "Failed to allocate recirculation id");
- ctx->error = XLATE_NO_RECIRCULATION_CONTEXT;
+ if (!ctx->xin->allow_side_effects && !ctx->xin->xcache) {
return 0;
}
- recirc_refs_add(&ctx->xout->recircs, id);
+ put_controller_user_action(ctx, false, true, recirc_id,
+ ctx->pause->max_len,
+ ctx->pause->reason,
+ ctx->pause->controller_id);
+ } else {
if (ctx->recirc_update_dp_hash) {
struct ovs_action_hash *act_hash;
@@ -4544,12 +4511,12 @@ finish_freezing__(struct xlate_ctx *ctx, uint8_t table)
act_hash->hash_alg = OVS_HASH_ALG_L4; /* Make configurable. */
act_hash->hash_basis = 0; /* Make configurable. */
}
- nl_msg_put_u32(ctx->odp_actions, OVS_ACTION_ATTR_RECIRC, id);
+ nl_msg_put_u32(ctx->odp_actions, OVS_ACTION_ATTR_RECIRC, recirc_id);
}
/* Undo changes done by freezing. */
ctx_cancel_freeze(ctx);
- return id;
+ return recirc_id;
}
/* Called only when we're freezing. */
@@ -6120,8 +6087,6 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len,
controller = ofpact_get_CONTROLLER(a);
if (controller->pause) {
ctx->pause = controller;
- ctx->xout->slow |= SLOW_PAUSE;
- *ctx->paused_flow = ctx->xin->flow;
ctx_trigger_freeze(ctx);
a = ofpact_next(a);
} else {
@@ -6756,7 +6721,6 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout)
uint64_t frozen_actions_stub[1024 / 8];
uint64_t actions_stub[256 / 8];
struct ofpbuf scratch_actions = OFPBUF_STUB_INITIALIZER(actions_stub);
- struct flow paused_flow;
struct xlate_ctx ctx = {
.xin = xin,
.xout = xout,
@@ -6792,7 +6756,6 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout)
.recirc_update_dp_hash = false,
.frozen_actions = OFPBUF_STUB_INITIALIZER(frozen_actions_stub),
.pause = NULL,
- .paused_flow = &paused_flow,
.was_mpls = false,
.conntracked = false,
@@ -4586,7 +4586,6 @@ ofproto_dpif_xcache_execute(struct ofproto_dpif *ofproto,
case XC_NORMAL:
case XC_GROUP:
case XC_TNL_NEIGH:
- case XC_CONTROLLER:
case XC_TUNNEL_HEADER:
xlate_push_stats_entry(entry, stats);
break;
@@ -260,8 +260,8 @@ userspace(pid=6633,flow_sample(probability=123,collector_set_id=1234,obs_domain_
userspace(pid=6633,flow_sample(probability=123,collector_set_id=1234,obs_domain_id=2345,obs_point_id=3456,output_port=10,egress),tunnel_out_port=10)
userspace(pid=6633,ipfix(output_port=10))
userspace(pid=6633,ipfix(output_port=10),tunnel_out_port=10)
-userspace(pid=6633,controller(reason=1,dont_send=0,recirc_id=4444,rule_cookie=0x5555,controller_id=0,max_len=65535))
-userspace(pid=6633,controller(reason=1,dont_send=1,recirc_id=4444,rule_cookie=0x5555,controller_id=0,max_len=65535))
+userspace(pid=6633,controller(reason=1,dont_send=0,continuation=1,recirc_id=4444,rule_cookie=0x5555,controller_id=0,max_len=65535))
+userspace(pid=6633,controller(reason=1,dont_send=1,continuation=0,recirc_id=4444,rule_cookie=0x5555,controller_id=0,max_len=65535))
set(in_port(2))
set(eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15))
set(eth(src=00:01:02:03:04:05,dst=10:11:12:13:14:15/ff:ff:ff:00:00:00))
@@ -784,7 +784,7 @@ AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:
AT_CHECK([tail -4 stdout], [0], [
Final flow: ip,in_port=1,vlan_tci=0x0000,dl_src=50:54:00:00:00:05,dl_dst=50:54:00:00:00:07,nw_src=192.168.0.1,nw_dst=192.168.0.2,nw_proto=111,nw_tos=0,nw_ecn=0,nw_ttl=1
Megaflow: recirc_id=0,eth,ip,in_port=1,nw_ttl=2,nw_frag=no
-Datapath actions: set(ipv4(ttl=1)),2,userspace(pid=0,controller(reason=2,dont_send=0,recirc_id=1,rule_cookie=0,controller_id=0,max_len=65535)),4
+Datapath actions: set(ipv4(ttl=1)),2,userspace(pid=0,controller(reason=2,dont_send=0,continuation=0,recirc_id=1,rule_cookie=0,controller_id=0,max_len=65535)),4
])
AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=111,tos=0,ttl=3,frag=no)'], [0], [stdout])
AT_CHECK([tail -2 stdout], [0],
@@ -1681,7 +1681,7 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
AT_CHECK([ovs-appctl dpctl/dump-flows | sed 's/.*\(packets:\)/\1/' | sed 's/used:[[0-9]].[[0-9]]*s/used:0.001s/'], [0], [dnl
flow-dump from non-dpdk interfaces:
-packets:1, bytes:14, used:0.001s, actions:userspace(pid=0,controller(reason=1,dont_send=0,recirc_id=1,rule_cookie=0,controller_id=0,max_len=65535))
+packets:1, bytes:14, used:0.001s, actions:userspace(pid=0,controller(reason=1,dont_send=0,continuation=0,recirc_id=1,rule_cookie=0,controller_id=0,max_len=65535))
])
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
@@ -1706,7 +1706,7 @@ done
AT_CHECK([ovs-appctl dpctl/dump-flows | sed 's/.*\(packets:\)/\1/' | sed 's/used:[[0-9]].[[0-9]]*s/used:0.001s/'], [0], [dnl
flow-dump from non-dpdk interfaces:
-packets:7, bytes:98, used:0.001s, actions:sample(sample=100.0%,actions(meter(0),userspace(pid=0,controller(reason=1,dont_send=0,recirc_id=2,rule_cookie=0,controller_id=0,max_len=65535))))
+packets:7, bytes:98, used:0.001s, actions:sample(sample=100.0%,actions(meter(0),userspace(pid=0,controller(reason=1,dont_send=0,continuation=0,recirc_id=2,rule_cookie=0,controller_id=0,max_len=65535))))
])
AT_CHECK([ovs-appctl time/warp 1], [0], [ignore])
@@ -7429,8 +7429,8 @@ for dl_src in 00 01; do
done
sleep 1 # wait for the datapath flow installed
AT_CHECK_UNQUOTED([strip_ufid < ovs-vswitchd.log | filter_flow_install | strip_used], [0], [dnl
-recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=60:66:66:66:66:00),eth_type(0x8847),mpls(label=20,tc=0,ttl=32,bos=0,label=20,tc=0,ttl=32,bos=1), actions:push_mpls(label=20,tc=0,ttl=32,bos=0,eth_type=0x8847),userspace(pid=0,controller(reason=1,dont_send=0,recirc_id=1,rule_cookie=0,controller_id=0,max_len=65535))
-recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=60:66:66:66:66:01),eth_type(0x8847),mpls(label=20/0x0,tc=0/0,ttl=32/0x0,bos=0/1,label=20/0xfffff,tc=0/7,ttl=32/0xff,bos=1/1), actions:pop_mpls(eth_type=0x8847),userspace(pid=0,controller(reason=1,dont_send=0,recirc_id=1,rule_cookie=0,controller_id=0,max_len=65535))
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=60:66:66:66:66:00),eth_type(0x8847),mpls(label=20,tc=0,ttl=32,bos=0,label=20,tc=0,ttl=32,bos=1), actions:push_mpls(label=20,tc=0,ttl=32,bos=0,eth_type=0x8847),userspace(pid=0,controller(reason=1,dont_send=0,continuation=0,recirc_id=1,rule_cookie=0,controller_id=0,max_len=65535))
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=60:66:66:66:66:01),eth_type(0x8847),mpls(label=20/0x0,tc=0/0,ttl=32/0x0,bos=0/1,label=20/0xfffff,tc=0/7,ttl=32/0xff,bos=1/1), actions:pop_mpls(eth_type=0x8847),userspace(pid=0,controller(reason=1,dont_send=0,continuation=0,recirc_id=1,rule_cookie=0,controller_id=0,max_len=65535))
])
OVS_VSWITCHD_STOP
@@ -7468,8 +7468,8 @@ for dl_src in 00 01; do
done
sleep 1 # wait for the datapath flow installed
AT_CHECK_UNQUOTED([strip_ufid < ovs-vswitchd.log | filter_flow_install | strip_used], [0], [dnl
-recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=60:66:66:66:66:00),eth_type(0x8847),mpls(label=20,tc=0,ttl=32,bos=0,label=20,tc=0,ttl=32,bos=1), actions:push_mpls(label=20,tc=0,ttl=32,bos=0,eth_type=0x8847),userspace(pid=0,controller(reason=1,dont_send=0,recirc_id=1,rule_cookie=0,controller_id=0,max_len=65535))
-recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=60:66:66:66:66:01),eth_type(0x8847),mpls(label=20/0x0,tc=0/0,ttl=32/0x0,bos=0/1,label=20/0xfffff,tc=0/7,ttl=32/0xff,bos=1/1), actions:pop_mpls(eth_type=0x8847),userspace(pid=0,controller(reason=1,dont_send=0,recirc_id=1,rule_cookie=0,controller_id=0,max_len=65535))
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=60:66:66:66:66:00),eth_type(0x8847),mpls(label=20,tc=0,ttl=32,bos=0,label=20,tc=0,ttl=32,bos=1), actions:push_mpls(label=20,tc=0,ttl=32,bos=0,eth_type=0x8847),userspace(pid=0,controller(reason=1,dont_send=0,continuation=0,recirc_id=1,rule_cookie=0,controller_id=0,max_len=65535))
+recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth(src=60:66:66:66:66:01),eth_type(0x8847),mpls(label=20/0x0,tc=0/0,ttl=32/0x0,bos=0/1,label=20/0xfffff,tc=0/7,ttl=32/0xff,bos=1/1), actions:pop_mpls(eth_type=0x8847),userspace(pid=0,controller(reason=1,dont_send=0,continuation=0,recirc_id=1,rule_cookie=0,controller_id=0,max_len=65535))
])
OVS_VSWITCHD_STOP
@@ -303,8 +303,8 @@ OVS_WAIT_UNTIL([ovs-appctl -t ovs-ofctl exit])
dnl Make sure that both flows have been installed
AT_CHECK([ovs-appctl dpctl/dump-flows | flow_dump_prepend_pmd], [0], [dnl
-0 recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:0, bytes:0, used:never, actions:userspace(pid=0,controller(reason=1,dont_send=0,recirc_id=1,rule_cookie=0,controller_id=0,max_len=65535))
-1 recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:0, bytes:0, used:never, actions:userspace(pid=0,controller(reason=1,dont_send=0,recirc_id=1,rule_cookie=0,controller_id=0,max_len=65535))
+0 recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:0, bytes:0, used:never, actions:userspace(pid=0,controller(reason=1,dont_send=0,continuation=0,recirc_id=1,rule_cookie=0,controller_id=0,max_len=65535))
+1 recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:0, bytes:0, used:never, actions:userspace(pid=0,controller(reason=1,dont_send=0,continuation=0,recirc_id=1,rule_cookie=0,controller_id=0,max_len=65535))
])
AT_CHECK([cat ofctl_monitor.log], [0], [dnl
@@ -164,7 +164,7 @@ AT_CHECK([ovs-ofctl dump-ports int-br | grep 'port 5'], [0], [dnl
port 5: rx pkts=1, bytes=98, drop=?, errs=?, frame=?, over=?, crc=?
])
AT_CHECK([ovs-appctl dpif/dump-flows int-br | grep 'in_port(6081)'], [0], [dnl
-tunnel(tun_id=0x7b,ipv6_src=2001:cafe::92,ipv6_dst=2001:cafe::88,geneve({class=0xffff,type=0x80,len=4,0xa/0xf}{class=0xffff,type=0,len=4}),flags(-df-csum+key)),recirc_id(0),in_port(6081),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:0, bytes:0, used:never, actions:userspace(pid=0,controller(reason=1,dont_send=0,recirc_id=3,rule_cookie=0,controller_id=0,max_len=65535))
+tunnel(tun_id=0x7b,ipv6_src=2001:cafe::92,ipv6_dst=2001:cafe::88,geneve({class=0xffff,type=0x80,len=4,0xa/0xf}{class=0xffff,type=0,len=4}),flags(-df-csum+key)),recirc_id(0),in_port(6081),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:0, bytes:0, used:never, actions:userspace(pid=0,controller(reason=1,dont_send=0,continuation=0,recirc_id=3,rule_cookie=0,controller_id=0,max_len=65535))
])
ovs-appctl time/warp 10000
@@ -215,7 +215,7 @@ AT_CHECK([ovs-ofctl dump-ports int-br | grep 'port 5'], [0], [dnl
port 5: rx pkts=1, bytes=98, drop=?, errs=?, frame=?, over=?, crc=?
])
AT_CHECK([ovs-appctl dpif/dump-flows int-br | grep 'in_port(6081)'], [0], [dnl
-tunnel(tun_id=0x7b,src=1.1.2.92,dst=1.1.2.88,geneve({class=0xffff,type=0x80,len=4,0xa/0xf}{class=0xffff,type=0,len=4}),flags(-df-csum+key)),recirc_id(0),in_port(6081),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:0, bytes:0, used:never, actions:userspace(pid=0,controller(reason=1,dont_send=0,recirc_id=3,rule_cookie=0,controller_id=0,max_len=65535))
+tunnel(tun_id=0x7b,src=1.1.2.92,dst=1.1.2.88,geneve({class=0xffff,type=0x80,len=4,0xa/0xf}{class=0xffff,type=0,len=4}),flags(-df-csum+key)),recirc_id(0),in_port(6081),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(frag=no), packets:0, bytes:0, used:never, actions:userspace(pid=0,controller(reason=1,dont_send=0,continuation=0,recirc_id=3,rule_cookie=0,controller_id=0,max_len=65535))
])
ovs-appctl time/warp 10000
A previous patch removed slow-pathing for controller actions with the exception of ones that specified "pause". This commit removes that restriction so that no controller actions are slow-pathed. Signed-off-by: Justin Pettit <jpettit@ovn.org> --- v1->v2: Changes suggested by Ben. --- lib/odp-util.c | 9 ++- lib/odp-util.h | 2 +- ofproto/ofproto-dpif-upcall.c | 31 ++++++-- ofproto/ofproto-dpif-xlate-cache.c | 13 ---- ofproto/ofproto-dpif-xlate-cache.h | 1 - ofproto/ofproto-dpif-xlate.c | 151 ++++++++++++++----------------------- ofproto/ofproto-dpif.c | 1 - tests/odp.at | 4 +- tests/ofproto-dpif.at | 14 ++-- tests/pmd.at | 4 +- tests/tunnel-push-pop-ipv6.at | 2 +- tests/tunnel-push-pop.at | 2 +- 12 files changed, 102 insertions(+), 132 deletions(-)