summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAaron Conole <aconole@redhat.com>2019-05-21 14:16:31 -0400
committerBen Pfaff <blp@ovn.org>2019-05-24 09:50:53 -0700
commit93346d889271d8e2140ffb64e96168286b8df112 (patch)
tree40505b056e9386ffedfde8c042fe60c756f6e8c7 /lib
parent8c7130da98c55bdf13eae62b5250434f8dfd366b (diff)
downloadopenvswitch-93346d889271d8e2140ffb64e96168286b8df112.tar.gz
conntrack: add display support for sctp
Currently, only the netlink datapath supports SCTP connection tracking, but at least this removes the warning message that will pop up when running something like: ovs-appctl dpctl/dump-conntrack This doesn't impact any conntrack functionality, just the display. Signed-off-by: Aaron Conole <aconole@redhat.com> Signed-off-by: Ben Pfaff <blp@ovn.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/ct-dpif.c19
-rw-r--r--lib/ct-dpif.h25
-rw-r--r--lib/netlink-conntrack.c70
3 files changed, 113 insertions, 1 deletions
diff --git a/lib/ct-dpif.c b/lib/ct-dpif.c
index b2c9b4309..5d8a75d3a 100644
--- a/lib/ct-dpif.c
+++ b/lib/ct-dpif.c
@@ -428,6 +428,12 @@ const char *ct_dpif_tcp_state_string[] = {
#undef CT_DPIF_TCP_STATE
};
+const char *ct_dpif_sctp_state_string[] = {
+#define CT_DPIF_SCTP_STATE(STATE) [CT_DPIF_SCTP_STATE_##STATE] = #STATE,
+ CT_DPIF_SCTP_STATES
+#undef CT_DPIF_SCTP_STATE
+};
+
static void
ct_dpif_format_enum__(struct ds *ds, const char *title, unsigned int state,
const char *names[], unsigned int max)
@@ -498,6 +504,16 @@ ct_dpif_format_protoinfo_tcp_verbose(struct ds *ds,
}
static void
+ct_dpif_format_protoinfo_sctp(struct ds *ds,
+ const struct ct_dpif_protoinfo *protoinfo)
+{
+ ct_dpif_format_enum(ds, "state=", protoinfo->sctp.state,
+ ct_dpif_sctp_state_string);
+ ds_put_format(ds, ",vtag_orig=%" PRIu32 ",vtag_reply=%" PRIu32,
+ protoinfo->sctp.vtag_orig, protoinfo->sctp.vtag_reply);
+}
+
+static void
ct_dpif_format_protoinfo(struct ds *ds, const char *title,
const struct ct_dpif_protoinfo *protoinfo,
bool verbose)
@@ -514,6 +530,9 @@ ct_dpif_format_protoinfo(struct ds *ds, const char *title,
ct_dpif_format_protoinfo_tcp(ds, protoinfo);
}
break;
+ case IPPROTO_SCTP:
+ ct_dpif_format_protoinfo_sctp(ds, protoinfo);
+ break;
}
if (title) {
ds_put_cstr(ds, ")");
diff --git a/lib/ct-dpif.h b/lib/ct-dpif.h
index 2628c2b68..14178bb7c 100644
--- a/lib/ct-dpif.h
+++ b/lib/ct-dpif.h
@@ -101,6 +101,26 @@ enum ct_dpif_tcp_flags {
#undef CT_DPIF_TCP_FLAG
};
+extern const char *ct_dpif_sctp_state_string[];
+
+#define CT_DPIF_SCTP_STATES \
+ CT_DPIF_SCTP_STATE(CLOSED) \
+ CT_DPIF_SCTP_STATE(COOKIE_WAIT) \
+ CT_DPIF_SCTP_STATE(COOKIE_ECHOED) \
+ CT_DPIF_SCTP_STATE(ESTABLISHED) \
+ CT_DPIF_SCTP_STATE(SHUTDOWN_SENT) \
+ CT_DPIF_SCTP_STATE(SHUTDOWN_RECD) \
+ CT_DPIF_SCTP_STATE(SHUTDOWN_ACK_SENT) \
+ CT_DPIF_SCTP_STATE(HEARTBEAT_SENT) \
+ CT_DPIF_SCTP_STATE(HEARTBEAT_ACKED) \
+ CT_DPIF_SCTP_STATE(MAX_NUM)
+
+enum ct_dpif_sctp_state {
+#define CT_DPIF_SCTP_STATE(STATE) CT_DPIF_SCTP_STATE_##STATE,
+ CT_DPIF_SCTP_STATES
+#undef CT_DPIF_SCTP_STATE
+};
+
struct ct_dpif_protoinfo {
uint16_t proto; /* IPPROTO_* */
union {
@@ -112,6 +132,11 @@ struct ct_dpif_protoinfo {
uint8_t flags_orig;
uint8_t flags_reply;
} tcp;
+ struct {
+ uint8_t state;
+ uint32_t vtag_orig;
+ uint32_t vtag_reply;
+ } sctp;
};
};
diff --git a/lib/netlink-conntrack.c b/lib/netlink-conntrack.c
index 42be1d9ce..7631ba5d5 100644
--- a/lib/netlink-conntrack.c
+++ b/lib/netlink-conntrack.c
@@ -717,6 +717,73 @@ nl_ct_parse_protoinfo_tcp(struct nlattr *nla,
return parsed;
}
+/* Translate netlink SCTP state to CT_DPIF_SCTP state. */
+static uint8_t
+nl_ct_sctp_state_to_dpif(uint8_t state)
+{
+#ifdef _WIN32
+ /* For now, return the CT_DPIF_SCTP state. Not sure what windows does. */
+ return state;
+#else
+ switch (state) {
+ case SCTP_CONNTRACK_COOKIE_WAIT:
+ return CT_DPIF_SCTP_STATE_COOKIE_WAIT;
+ case SCTP_CONNTRACK_COOKIE_ECHOED:
+ return CT_DPIF_SCTP_STATE_COOKIE_ECHOED;
+ case SCTP_CONNTRACK_ESTABLISHED:
+ return CT_DPIF_SCTP_STATE_ESTABLISHED;
+ case SCTP_CONNTRACK_SHUTDOWN_SENT:
+ return CT_DPIF_SCTP_STATE_SHUTDOWN_SENT;
+ case SCTP_CONNTRACK_SHUTDOWN_RECD:
+ return CT_DPIF_SCTP_STATE_SHUTDOWN_RECD;
+ case SCTP_CONNTRACK_SHUTDOWN_ACK_SENT:
+ return CT_DPIF_SCTP_STATE_SHUTDOWN_ACK_SENT;
+ case SCTP_CONNTRACK_HEARTBEAT_SENT:
+ return CT_DPIF_SCTP_STATE_HEARTBEAT_SENT;
+ case SCTP_CONNTRACK_HEARTBEAT_ACKED:
+ return CT_DPIF_SCTP_STATE_HEARTBEAT_ACKED;
+ case SCTP_CONNTRACK_CLOSED:
+ /* Fall Through. */
+ case SCTP_CONNTRACK_NONE:
+ /* Fall Through. */
+ default:
+ return CT_DPIF_SCTP_STATE_CLOSED;
+ }
+#endif
+}
+
+static bool
+nl_ct_parse_protoinfo_sctp(struct nlattr *nla,
+ struct ct_dpif_protoinfo *protoinfo)
+{
+ static const struct nl_policy policy[] = {
+ [CTA_PROTOINFO_SCTP_STATE] = { .type = NL_A_U8, .optional = false },
+ [CTA_PROTOINFO_SCTP_VTAG_ORIGINAL] = { .type = NL_A_U32,
+ .optional = false },
+ [CTA_PROTOINFO_SCTP_VTAG_REPLY] = { .type = NL_A_U32,
+ .optional = false },
+ };
+ struct nlattr *attrs[ARRAY_SIZE(policy)];
+ bool parsed;
+
+ parsed = nl_parse_nested(nla, policy, attrs, ARRAY_SIZE(policy));
+ if (parsed) {
+ protoinfo->proto = IPPROTO_SCTP;
+
+ protoinfo->sctp.state = nl_ct_sctp_state_to_dpif(
+ nl_attr_get_u8(attrs[CTA_PROTOINFO_SCTP_STATE]));
+ protoinfo->sctp.vtag_orig = nl_attr_get_u32(
+ attrs[CTA_PROTOINFO_SCTP_VTAG_ORIGINAL]);
+ protoinfo->sctp.vtag_reply = nl_attr_get_u32(
+ attrs[CTA_PROTOINFO_SCTP_VTAG_REPLY]);
+ } else {
+ VLOG_ERR_RL(&rl, "Could not parse nested SCTP protoinfo options. "
+ "Possibly incompatible Linux kernel version.");
+ }
+
+ return parsed;
+}
+
static bool
nl_ct_parse_protoinfo(struct nlattr *nla, struct ct_dpif_protoinfo *protoinfo)
{
@@ -737,7 +804,8 @@ nl_ct_parse_protoinfo(struct nlattr *nla, struct ct_dpif_protoinfo *protoinfo)
parsed = nl_ct_parse_protoinfo_tcp(attrs[CTA_PROTOINFO_TCP],
protoinfo);
} else if (attrs[CTA_PROTOINFO_SCTP]) {
- VLOG_WARN_RL(&rl, "SCTP protoinfo not yet supported!");
+ parsed = nl_ct_parse_protoinfo_sctp(attrs[CTA_PROTOINFO_SCTP],
+ protoinfo);
} else {
VLOG_WARN_RL(&rl, "Empty protoinfo!");
}