@@ -1885,6 +1885,32 @@ out:
return error;
}
+
+static int
+dpctl_icing_dp(int argc, const char *argv[], struct dpctl_params *dpctl_p)
+{
+ struct dpif *dpif;
+ int error;
+
+ error = parsed_dpif_open(argv[1], false, &dpif);
+ if (error) {
+ dpctl_error(dpctl_p, error, "icing_dp");
+ return error;
+ }
+
+ if (argc > 2) {
+ bool icing_status = false;
+ if (!strcmp(argv[2], "enabled")) {
+ icing_status = true;
+ }
+ dpif_set_ice_status(dpif, icing_status);
+ }
+
+ dpctl_print(dpctl_p, dpif_get_ice_status(dpif) ? "enabled" : "disabled");
+ dpif_close(dpif);
+ return 0;
+}
+
static const struct dpctl_command all_commands[] = {
{ "add-dp", "dp [iface...]", 1, INT_MAX, dpctl_add_dp, DP_RW },
@@ -1913,6 +1939,7 @@ static const struct dpctl_command all_commands[] = {
{ "parse-actions", "actions", 1, INT_MAX, dpctl_parse_actions, DP_RO },
{ "normalize-actions", "actions",
2, INT_MAX, dpctl_normalize_actions, DP_RO },
+ { "datapath-icing", "dp [enabled|disabled]", 1, 2, dpctl_icing_dp, DP_RW },
{ NULL, NULL, 0, 0, NULL, DP_RO },
};
@@ -5790,6 +5790,8 @@ const struct dpif_class dpif_netdev_class = {
dpif_netdev_meter_set,
dpif_netdev_meter_get,
dpif_netdev_meter_del,
+ NULL,
+ NULL
};
static void
@@ -196,6 +196,7 @@ struct dpif_netlink {
/* Change notification. */
struct nl_sock *port_notifier; /* vport multicast group subscriber. */
bool refresh_channels;
+
};
static void report_loss(struct dpif_netlink *, struct dpif_channel *,
@@ -211,6 +212,8 @@ static int ovs_vport_family;
static int ovs_flow_family;
static int ovs_packet_family;
+static bool ice_status = false;
+
/* Generic Netlink multicast groups for OVS.
*
* Initialized by dpif_netlink_init(). */
@@ -707,6 +710,9 @@ dpif_netlink_destroy(struct dpif *dpif_)
dpif_netlink_dp_init(&dp);
dp.cmd = OVS_DP_CMD_DEL;
dp.dp_ifindex = dpif->dp_ifindex;
+ if (ice_status) {
+ return 0;
+ }
return dpif_netlink_dp_transact(&dp, NULL, NULL);
}
@@ -1159,6 +1165,10 @@ dpif_netlink_flow_flush(struct dpif *dpif_)
flow.cmd = OVS_FLOW_CMD_DEL;
flow.dp_ifindex = dpif->dp_ifindex;
+ if (ice_status) {
+ return 0;
+ }
+
if (netdev_is_flow_api_enabled()) {
netdev_ports_flow_flush(dpif_->dpif_class);
}
@@ -1916,13 +1926,15 @@ dpif_netlink_operate__(struct dpif_netlink *dpif,
break;
case DPIF_OP_FLOW_DEL:
- del = &op->u.flow_del;
- dpif_netlink_init_flow_del(dpif, del, &flow);
- if (del->stats) {
- flow.nlmsg_flags |= NLM_F_ECHO;
- aux->txn.reply = &aux->reply;
+ if (!ice_status) {
+ del = &op->u.flow_del;
+ dpif_netlink_init_flow_del(dpif, del, &flow);
+ if (del->stats) {
+ flow.nlmsg_flags |= NLM_F_ECHO;
+ aux->txn.reply = &aux->reply;
+ }
+ dpif_netlink_flow_to_ofpbuf(&flow, &aux->request);
}
- dpif_netlink_flow_to_ofpbuf(&flow, &aux->request);
break;
case DPIF_OP_EXECUTE:
@@ -1990,15 +2002,17 @@ dpif_netlink_operate__(struct dpif_netlink *dpif,
break;
case DPIF_OP_FLOW_DEL:
- del = &op->u.flow_del;
- if (del->stats) {
- if (!op->error) {
- struct dpif_netlink_flow reply;
-
- op->error = dpif_netlink_flow_from_ofpbuf(&reply,
- txn->reply);
+ if (!ice_status) {
+ del = &op->u.flow_del;
+ if (del->stats) {
if (!op->error) {
- dpif_netlink_flow_get_stats(&reply, del->stats);
+ struct dpif_netlink_flow reply;
+
+ op->error = dpif_netlink_flow_from_ofpbuf(&reply,
+ txn->reply);
+ if (!op->error) {
+ dpif_netlink_flow_get_stats(&reply, del->stats);
+ }
}
}
}
@@ -2156,7 +2170,9 @@ parse_flow_put(struct dpif_netlink *dpif, struct dpif_flow_put *put)
op.u.flow_del.terse = false;
opp = &op;
- dpif_netlink_operate__(dpif, &opp, 1);
+ if (!ice_status) {
+ dpif_netlink_operate__(dpif, &opp, 1);
+ }
}
VLOG_DBG("added flow");
@@ -2207,7 +2223,7 @@ try_send_to_netdev(struct dpif_netlink *dpif, struct dpif_op *op)
case DPIF_OP_FLOW_DEL: {
struct dpif_flow_del *del = &op->u.flow_del;
- if (!del->ufid) {
+ if (ice_status || !del->ufid) {
break;
}
@@ -2941,6 +2957,21 @@ dpif_netlink_meter_del(struct dpif *dpif OVS_UNUSED,
}
+
+static int
+dpif_netlink_set_ice_status(struct dpif *dpif_ OVS_UNUSED, bool set_ice_status)
+{
+ ice_status = set_ice_status;
+ return 0;
+}
+
+static bool
+dpif_netlink_get_ice_status(struct dpif *dpif_ OVS_UNUSED)
+{
+ return ice_status;
+}
+
+
const struct dpif_class dpif_netlink_class = {
"system",
NULL, /* init */
@@ -2990,6 +3021,8 @@ const struct dpif_class dpif_netlink_class = {
dpif_netlink_meter_set,
dpif_netlink_meter_get,
dpif_netlink_meter_del,
+ dpif_netlink_set_ice_status,
+ dpif_netlink_get_ice_status
};
static int
@@ -456,6 +456,14 @@ struct dpif_class {
* zero. */
int (*meter_del)(struct dpif *, ofproto_meter_id meter_id,
struct ofputil_meter_stats *, uint16_t n_bands);
+
+ /* Set / clear the 'ice' status of the 'dpif'. If this is set to 'true'
+ * the ice flag will stop any deletion or purging of flows from the flow
+ * tables which are implemented by 'dpif'. */
+ int (*set_ice_status)(struct dpif *, bool ice);
+
+ /* Get the 'ice' status of the 'dpif'. */
+ bool (*get_ice_status)(const struct dpif *);
};
extern const struct dpif_class dpif_netlink_class;
@@ -1953,3 +1953,25 @@ dpif_meter_del(struct dpif *dpif, ofproto_meter_id meter_id,
}
return error;
}
+
+int
+dpif_set_ice_status(struct dpif *dpif, bool ice)
+{
+ int error = EOPNOTSUPP;
+
+ if (dpif->dpif_class->set_ice_status) {
+ error = dpif->dpif_class->set_ice_status(dpif, ice);
+ }
+
+ return error;
+}
+
+bool
+dpif_get_ice_status(struct dpif *dpif)
+{
+ if (dpif->dpif_class->get_ice_status) {
+ return dpif->dpif_class->get_ice_status(dpif);
+ }
+
+ return false;
+}
@@ -871,6 +871,8 @@ int dpif_meter_del(struct dpif *, ofproto_meter_id meter_id,
struct ofputil_meter_stats *, uint16_t n_bands);
/* Miscellaneous. */
+int dpif_set_ice_status(struct dpif *, bool ice);
+bool dpif_get_ice_status(struct dpif *);
void dpif_get_netflow_ids(const struct dpif *,
uint8_t *engine_type, uint8_t *engine_id);
Introduce a way of telling the revalidators not to delete flows from the datapath. This means that even during the dump/sweep behavior, flows which might have been expired will stick around in the kernel datapath. Such an effect is potentially disastrous (since the kernel flow cache will never empty, only fill). On the other hand, in conjunction with other user actions, this can implement a "graceful restart." This will be used in an upcoming commit. Signed-off-by: Aaron Conole <aconole@redhat.com> --- lib/dpctl.c | 27 ++++++++++++++++++++++ lib/dpif-netdev.c | 2 ++ lib/dpif-netlink.c | 65 ++++++++++++++++++++++++++++++++++++++++------------- lib/dpif-provider.h | 8 +++++++ lib/dpif.c | 22 ++++++++++++++++++ lib/dpif.h | 2 ++ 6 files changed, 110 insertions(+), 16 deletions(-)