[ovs-dev] [PATCH 5/5] Netlink.c: Added netlink put APIs.

Ankur Sharma ankursharma at vmware.com
Wed Sep 3 01:05:23 UTC 2014


In this change we have added the APIs for putting
netlink headers, attributes in a buffer.

The buffer is managed through NetlinkBuf.[c|h].
---
 datapath-windows/ovsext/Netlink/Netlink.c | 403 +++++++++++++++++++++++++++++-
 datapath-windows/ovsext/Netlink/Netlink.h |  28 +++
 2 files changed, 427 insertions(+), 4 deletions(-)

diff --git a/datapath-windows/ovsext/Netlink/Netlink.c b/datapath-windows/ovsext/Netlink/Netlink.c
index 90a633b..8c6b139 100644
--- a/datapath-windows/ovsext/Netlink/Netlink.c
+++ b/datapath-windows/ovsext/Netlink/Netlink.c
@@ -24,6 +24,402 @@
 #define OVS_DBG_MOD OVS_DBG_NETLINK
 #include "Debug.h"
 
+/* ==========================================================================
+ * This file provides simple netlink get, put and validation APIs.
+ * Most of the code is on similar lines as userspace netlink implementation.
+ * 
+ * TODO: Convert these methods to inline.
+ * ==========================================================================
+ */
+
+/*
+ * ---------------------------------------------------------------------------
+ * Adds Netlink Header to the NL_BUF.
+ * ---------------------------------------------------------------------------
+ */
+BOOLEAN
+NlMsgPutNlHdr(PNL_BUF buf, PNL_MSG_HDR nlMsg)
+{
+    if ((NlBufCopyAtOffset(buf, (PCHAR)nlMsg, NLMSG_HDRLEN, 0))) {
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Adds Genl Header to the NL_BUF.
+ * ---------------------------------------------------------------------------
+ */
+BOOLEAN
+NlMsgPutGenlHdr(PNL_BUF buf, PGENL_MSG_HDR genlMsg)
+{
+    if ((NlBufCopyAtOffset(buf, (PCHAR)genlMsg, GENL_HDRLEN, NLMSG_HDRLEN))) {
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Adds OVS Header to the NL_BUF.
+ * ---------------------------------------------------------------------------
+ */
+BOOLEAN
+NlMsgPutOvsHdr(PNL_BUF buf, POVS_HDR ovsHdr)
+{
+    if ((NlBufCopyAtOffset(buf, (PCHAR)ovsHdr, OVS_HDRLEN,
+                           GENL_HDRLEN + NLMSG_HDRLEN))) {
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Adds data of length 'len' to the tail end of NL_BUF.
+ * Refer nl_msg_put for more details.
+ * ---------------------------------------------------------------------------
+ */
+BOOLEAN
+NlMsgPutTail(PNL_BUF buf, const PCHAR data, UINT32 len)
+{
+    len = NLMSG_ALIGN(len);
+    if (NlBufCopyAtTail(buf, data, len)) {
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * memsets length 'len' at tail end of NL_BUF.
+ * Refer nl_msg_put_uninit for more details.
+ * ---------------------------------------------------------------------------
+ */
+PCHAR
+NlMsgPutTailUninit(PNL_BUF buf, UINT32 len)
+{
+    len = NLMSG_ALIGN(len);
+    return NlBufCopyAtTailUninit(buf, len);
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Adds an attribute to the tail end of buffer. It does
+ * not copy the attribute payload.
+ * Refer nl_msg_put_unspec_uninit for more details.
+ * ---------------------------------------------------------------------------
+ */
+PCHAR
+NlMsgPutTailUnspecUninit(PNL_BUF buf, UINT16 type, UINT16 len)
+{
+    PCHAR ret = NULL;
+    UINT16 totalLen = NLA_HDRLEN + len;
+    PNL_ATTR nla = (PNL_ATTR)(NlMsgPutTailUninit(buf, totalLen));
+
+    if (!nla) {
+        goto done;
+    }
+
+    ret = (PCHAR)(nla + 1);
+    nla->nlaLen = totalLen;
+    nla->nlaType = type;
+
+done:
+    return ret;
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Adds an attribute to the tail end of buffer. It copies attribute
+ * payload as well.
+ * Refer nl_msg_put_unspec for more details.
+ * ---------------------------------------------------------------------------
+ */
+BOOLEAN
+NlMsgPutTailUnspec(PNL_BUF buf, UINT16 type, PCHAR data, UINT16 len)
+{
+    BOOLEAN ret = TRUE;
+    PCHAR nlaData = NlMsgPutTailUnspecUninit(buf, type, len);
+
+    if (!nlaData) {
+        ret = FALSE;
+        goto done;
+    }
+
+    RtlCopyMemory(nlaData, data, len);
+
+done:
+    return ret;
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Adds an attribute of 'type' and no payload at the tail end of buffer.
+ * Refer nl_msg_put_flag for more details.
+ * ---------------------------------------------------------------------------
+ */
+BOOLEAN
+NlMsgPutTailFlag(PNL_BUF buf, UINT16 type)
+{
+    BOOLEAN ret = TRUE;
+    PCHAR nlaData = NlMsgPutTailUnspecUninit(buf, type, 0);
+
+    if (!nlaData) {
+        ret = FALSE;
+    }
+
+    return ret;
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Adds an attribute of 'type' and 8 bit payload at the tail end of buffer.
+ * Refer nl_msg_put_u8 for more details.
+ * ---------------------------------------------------------------------------
+ */
+BOOLEAN
+NlMsgPutTailU8(PNL_BUF buf, UINT16 type, UINT8 value)
+{
+    return (NlMsgPutTailUnspec(buf, type, (PCHAR)(&value), sizeof(value)));
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Adds an attribute of 'type' and 16 bit payload at the tail end of buffer.
+ * Refer nl_msg_put_u16 for more details.
+ * ---------------------------------------------------------------------------
+ */
+BOOLEAN
+NlMsgPutTailU16(PNL_BUF buf, UINT16 type, UINT16 value)
+{
+    return (NlMsgPutTailUnspec(buf, type, (PCHAR)(&value), sizeof(value)));
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Adds an attribute of 'type' and 32 bit payload at the tail end of buffer.
+ * Refer nl_msg_put_u32 for more details.
+ * ---------------------------------------------------------------------------
+ */
+BOOLEAN
+NlMsgPutTailU32(PNL_BUF buf, UINT16 type, UINT32 value)
+{
+    return (NlMsgPutTailUnspec(buf, type, (PCHAR)(&value), sizeof(value)));
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Adds an attribute of 'type' and 64 bit payload at the tail end of buffer.
+ * Refer nl_msg_put_u64 for more details.
+ * ---------------------------------------------------------------------------
+ */
+BOOLEAN
+NlMsgPutTailU64(PNL_BUF buf, UINT16 type, UINT64 value)
+{
+    return (NlMsgPutTailUnspec(buf, type, (PCHAR)(&value), sizeof(value)));
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Adds an attribute of 'type' and string payload.
+ * Refer nl_msg_put_string for more details.
+ * ---------------------------------------------------------------------------
+ */
+BOOLEAN
+NlMsgPutTailString(PNL_BUF buf, UINT16 type, PCHAR value)
+{
+    size_t strLen = strlen(value) + 1;
+#ifdef DBG
+    /* Attribute length should come within 16 bits (NL_ATTR).
+     * Not a likely case, hence validation only in debug mode. */
+    if ((strLen + PAD_SIZE(strLen, NLA_ALIGNTO)) > MAXUINT16) {
+        return FALSE;
+    }
+#endif
+
+    /* typecast to keep compiler happy */
+    return (NlMsgPutTailUnspec(buf, type, value,
+                               (UINT16)strLen));
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Adds data of length 'len' to the head of NL_BUF.
+ * Refer nl_msg_push for more details.
+ * ---------------------------------------------------------------------------
+ */
+BOOLEAN
+NlMsgPutHead(PNL_BUF buf, const PCHAR data, UINT32 len)
+{
+    len = NLMSG_ALIGN(len);
+    if (NlBufCopyAtHead(buf, data, len)) {
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * memsets length 'len' at head of NL_BUF.
+ * Refer nl_msg_push_uninit for more details.
+ * ---------------------------------------------------------------------------
+ */
+PCHAR
+NlMsgPutHeadUninit(PNL_BUF buf, UINT32 len)
+{
+    len = NLMSG_ALIGN(len);
+    return NlBufCopyAtHeadUninit(buf, len);
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Adds an attribute to the head of buffer. It does
+ * not copy the attribute payload.
+ * Refer nl_msg_push_unspec_uninit for more details.
+ * ---------------------------------------------------------------------------
+ */
+PCHAR
+NlMsgPutHeadUnspecUninit(PNL_BUF buf, UINT16 type, UINT16 len)
+{
+    PCHAR ret = NULL;
+    UINT16 totalLen = NLA_HDRLEN + len;
+    PNL_ATTR nla = (PNL_ATTR)(NlMsgPutHeadUninit(buf, totalLen));
+
+    if (!nla) {
+        goto done;
+    }
+
+    ret = (PCHAR)(nla + 1);
+    nla->nlaLen = totalLen;
+    nla->nlaType = type;
+
+done:
+    return ret;
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Adds an attribute to the head of buffer. It copies attribute
+ * payload as well.
+ * Refer nl_msg_push_unspec for more details.
+ * ---------------------------------------------------------------------------
+ */
+BOOLEAN
+NlMsgPutHeadUnspec(PNL_BUF buf, UINT16 type, PCHAR data, UINT16 len)
+{
+    BOOLEAN ret = TRUE;
+    PCHAR nlaData = NlMsgPutHeadUnspecUninit(buf, type, len);
+
+    if (!nlaData) {
+        ret = FALSE;
+        goto done;
+    }
+
+    RtlCopyMemory(nlaData, data, len);
+
+done:
+    return ret;
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Adds an attribute of 'type' and no payload at the head of buffer.
+ * Refer nl_msg_push_flag for more details.
+ * ---------------------------------------------------------------------------
+ */
+BOOLEAN
+NlMsgPutHeadFlag(PNL_BUF buf, UINT16 type)
+{
+    BOOLEAN ret = TRUE;
+    PCHAR nlaData = NlMsgPutHeadUnspecUninit(buf, type, 0);
+
+    if (!nlaData) {
+        ret = FALSE;
+    }
+
+    return ret;
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Adds an attribute of 'type' and 8 bit payload at the head of buffer.
+ * Refer nl_msg_push_u8 for more details.
+ * ---------------------------------------------------------------------------
+ */
+BOOLEAN
+NlMsgPutHeadU8(PNL_BUF buf, UINT16 type, UINT8 value)
+{
+    return (NlMsgPutHeadUnspec(buf, type, (PCHAR)(&value), sizeof(value)));
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Adds an attribute of 'type' and 16 bit payload at the head of buffer.
+ * Refer nl_msg_push_u16 for more details.
+ * ---------------------------------------------------------------------------
+ */
+BOOLEAN
+NlMsgPutHeadU16(PNL_BUF buf, UINT16 type, UINT16 value)
+{
+    return (NlMsgPutHeadUnspec(buf, type, (PCHAR)(&value), sizeof(value)));
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Adds an attribute of 'type' and 32 bit payload at the head of buffer.
+ * Refer nl_msg_push_u32 for more details.
+ * ---------------------------------------------------------------------------
+ */
+BOOLEAN
+NlMsgPutHeadU32(PNL_BUF buf, UINT16 type, UINT32 value)
+{
+    return (NlMsgPutHeadUnspec(buf, type, (PCHAR)(&value), sizeof(value)));
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Adds an attribute of 'type' and 64 bit payload at the head of buffer.
+ * Refer nl_msg_push_u64 for more details.
+ * ---------------------------------------------------------------------------
+ */
+BOOLEAN
+NlMsgPutHeadU64(PNL_BUF buf, UINT16 type, UINT64 value)
+{
+    return (NlMsgPutHeadUnspec(buf, type, (PCHAR)(&value), sizeof(value)));
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * Adds an attribute of 'type' and string payload.
+ * Refer nl_msg_push_string for more details.
+ * ---------------------------------------------------------------------------
+ */
+BOOLEAN
+NlMsgPutHeadString(PNL_BUF buf, UINT16 type, PCHAR value)
+{
+    size_t strLen = strlen(value) + 1;
+#ifdef DBG
+    /* Attribute length should come within 16 bits (NL_ATTR).
+     * Not a likely case, hence validation only in debug mode. */
+    if ((strLen + PAD_SIZE(strLen, NLA_ALIGNTO)) > MAXUINT16) {
+        return FALSE;
+    }
+#endif
+
+    /* typecast to keep compiler happy */
+    return (NlMsgPutHeadUnspec(buf, type, value,
+                               (UINT16)strLen));
+}
+
+/* Accessing netlink message payload */
+
 /*
  * ---------------------------------------------------------------------------
  * Netlink message accessing the payload.
@@ -173,7 +569,7 @@ NlAttrMaxLen(NL_ATTR_TYPE type)
     case NL_A_U16: return 2;
     case NL_A_U32: return 4;
     case NL_A_U64: return 8;
-    case NL_A_STRING: return SIZE_MAX;
+    case NL_A_STRING: return MAXUINT16;
     case NL_A_FLAG: return SIZE_MAX;
     case NL_A_NESTED: return SIZE_MAX;
     case N_NL_ATTR_TYPES:
@@ -408,8 +804,7 @@ NlAttrFindNested(const PNL_ATTR nla, UINT16 type)
  * attribute type validation parameters.
  * 'nla_offset' should be NLMSG_HDRLEN + GENL_HDRLEN + OVS_HEADER
  *
- * Returns NDIS_STATUS_SUCCESS normally.  Fails only if packet data cannot be accessed
- * (e.g. if Pkt_CopyBytesOut() returns an error).
+ * Returns BOOLEAN to indicate success/failure.
  *----------------------------------------------------------------------------
  */
 BOOLEAN NlAttrParse(const PNL_MSG_HDR nlMsg, UINT32 attrOffset,
@@ -421,7 +816,7 @@ BOOLEAN NlAttrParse(const PNL_MSG_HDR nlMsg, UINT32 attrOffset,
     UINT32 iter;
     BOOLEAN ret = FALSE;
 
-    memset(attrs, 0, n_attrs * sizeof *attrs);
+    RtlZeroMemory(attrs, n_attrs * sizeof *attrs);
 
     if ((NlMsgSize(nlMsg) < attrOffset) || (!(NlMsgAttrLen(nlMsg)))) {
         OVS_LOG_WARN("No attributes in nlMsg: %p at offset: %d",
diff --git a/datapath-windows/ovsext/Netlink/Netlink.h b/datapath-windows/ovsext/Netlink/Netlink.h
index 0edc2fa..04fd536 100644
--- a/datapath-windows/ovsext/Netlink/Netlink.h
+++ b/datapath-windows/ovsext/Netlink/Netlink.h
@@ -19,6 +19,7 @@
 
 #include "Types.h"
 #include "NetlinkProto.h"
+#include "NetlinkBuf.h"
 
 /* Netlink attribute types. */
 typedef enum
@@ -101,4 +102,31 @@ BOOLEAN NlAttrParse(const PNL_MSG_HDR nlMsg, UINT32 attrOffset,
 /* Netlink attribute validation */
 BOOLEAN NlAttrValidate(const PNL_ATTR, const PNL_POLICY);
 
+/* Put APis */
+BOOLEAN NlMsgPutNlHdr(PNL_BUF buf, PNL_MSG_HDR nlMsg);
+BOOLEAN NlMsgPutGenlHdr(PNL_BUF buf, PGENL_MSG_HDR genlMsg);
+BOOLEAN NlMsgPutOvsHdr(PNL_BUF buf, POVS_HDR ovsHdr);
+
+BOOLEAN NlMsgPutTail(PNL_BUF buf, const PCHAR data, UINT32 len);
+PCHAR NlMsgPutTailUninit(PNL_BUF buf, UINT32 len);
+PCHAR NlMsgPutTailUnspecUninit(PNL_BUF buf, UINT16 type, UINT16 len);
+BOOLEAN NlMsgPutTailUnspec(PNL_BUF buf, UINT16 type, PCHAR data, UINT16 len);
+BOOLEAN NlMsgPutTailFlag(PNL_BUF buf, UINT16 type);
+BOOLEAN NlMsgPutTailU8(PNL_BUF buf, UINT16 type, UINT8 value);
+BOOLEAN NlMsgPutTailU16(PNL_BUF buf, UINT16 type, UINT16 value);
+BOOLEAN NlMsgPutTailU32(PNL_BUF buf, UINT16 type, UINT32 value);
+BOOLEAN NlMsgPutTailU64(PNL_BUF buf, UINT16 type, UINT64 value);
+BOOLEAN NlMsgPutTailString(PNL_BUF buf, UINT16 type, PCHAR value);
+
+BOOLEAN NlMsgPutHead(PNL_BUF buf, const PCHAR data, UINT32 len);
+PCHAR NlMsgPutHeadUninit(PNL_BUF buf, UINT32 len);
+PCHAR NlMsgPutHeadUnspecUninit(PNL_BUF buf, UINT16 type, UINT16 len);
+BOOLEAN NlMsgPutHeadUnspec(PNL_BUF buf, UINT16 type, PCHAR data, UINT16 len);
+BOOLEAN NlMsgPutHeadFlag(PNL_BUF buf, UINT16 type);
+BOOLEAN NlMsgPutHeadU8(PNL_BUF buf, UINT16 type, UINT8 value);
+BOOLEAN NlMsgPutHeadU16(PNL_BUF buf, UINT16 type, UINT16 value);
+BOOLEAN NlMsgPutHeadU32(PNL_BUF buf, UINT16 type, UINT32 value);
+BOOLEAN NlMsgPutHeadU64(PNL_BUF buf, UINT16 type, UINT64 value);
+BOOLEAN NlMsgPutHeadString(PNL_BUF buf, UINT16 type, PCHAR value);
+
 #endif /* __NETLINK_H_ */
-- 
1.9.1




More information about the dev mailing list