summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--datapath-windows/automake.mk2
-rw-r--r--datapath-windows/ovsext/Netlink/NetlinkBuf.c349
-rw-r--r--datapath-windows/ovsext/Netlink/NetlinkBuf.h41
-rw-r--r--datapath-windows/ovsext/ovsext.vcxproj2
4 files changed, 394 insertions, 0 deletions
diff --git a/datapath-windows/automake.mk b/datapath-windows/automake.mk
index 5ea01976b..297a80932 100644
--- a/datapath-windows/automake.mk
+++ b/datapath-windows/automake.mk
@@ -32,6 +32,8 @@ EXTRA_DIST += \
datapath-windows/ovsext/Jhash.h \
datapath-windows/ovsext/Netlink/Netlink.c \
datapath-windows/ovsext/Netlink/Netlink.h \
+ datapath-windows/ovsext/Netlink/NetlinkBuf.c \
+ datapath-windows/ovsext/Netlink/NetlinkBuf.h \
datapath-windows/ovsext/Netlink/NetlinkProto.h \
datapath-windows/ovsext/NetProto.h \
datapath-windows/ovsext/Oid.c \
diff --git a/datapath-windows/ovsext/Netlink/NetlinkBuf.c b/datapath-windows/ovsext/Netlink/NetlinkBuf.c
new file mode 100644
index 000000000..590c803f0
--- /dev/null
+++ b/datapath-windows/ovsext/Netlink/NetlinkBuf.c
@@ -0,0 +1,349 @@
+/*
+ * Copyright (c) 2014 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* ==========================================================================
+ * This is a simple buffer mangement framework specific for netlink protocol.
+ * The name could be confused with ovsext/BufferMgmt.c. Ovsext/BufferMgmt.c
+ * deals with buffer mgmt for NBLs. Where as this framework deals with
+ * management of buffer that holds a netlink message.
+ *
+ * This framework provides APIs for putting/accessing data in a buffer. These
+ * APIs are used by driver's netlink protocol implementation.
+ *
+ * We can see this framework as a subset of ofpbuf in ovs userspace.
+ *
+ * This framework is NOT a generic buffer management framework (ofpbuf
+ * is a generic buffer mgmt framework) and provides only the functioanlities
+ * which would be useful for netlink protocol. Some of the key features are:
+ *
+ * a. It DOES NOT support automatic buffer reallocation.
+ * i. A netlink input/output message is a static buffer.
+ * b. The unused space is at the tail.
+ * c. There is no notion of headdroom.
+ * ==========================================================================
+ */
+#include <ndis.h>
+#include <netiodef.h>
+#include <intsafe.h>
+#include <ntintsafe.h>
+#include <ntstrsafe.h>
+#include <Strsafe.h>
+
+#ifdef OVS_DBG_MOD
+#undef OVS_DBG_MOD
+#endif
+#define OVS_DBG_MOD OVS_DBG_NETLINK
+#include "Debug.h"
+#include "NetlinkBuf.h"
+
+/* Returns used space in the buffer */
+#define NL_BUF_USED_SPACE(_buf) (_buf->bufLen - \
+ _buf->bufRemLen)
+
+/* Validates that offset is within buffer boundaries and will not
+ * create holes in the buffer.*/
+#define NL_BUF_IS_VALID_OFFSET(_buf, _offset) (_offset <= \
+ NL_BUF_TAIL_OFFSET(_buf) ? 1 : 0)
+
+/* Validates if new data of size _size can be added at offset _offset.
+ * This macor assumes that offset validation has been done.*/
+#define NL_BUF_CAN_ADD(_buf, _size, _offset) (((_offset + _size <= \
+ _buf->bufLen) && (_size \
+ <= _buf->bufRemLen)) ? \
+ 1 : 0)
+
+/* Returns the offset of tail wrt buffer head */
+#define NL_BUF_TAIL_OFFSET(_buf) (_buf->tail - _buf->head)
+
+static __inline VOID
+_NlBufCopyAtTailUnsafe(PNL_BUFFER nlBuf, PCHAR data, UINT32 len);
+static __inline VOID
+_NlBufCopyAtOffsetUnsafe(PNL_BUFFER nlBuf, PCHAR data, UINT32 len, UINT32 offset);
+
+/*
+ * --------------------------------------------------------------------------
+ * NlBufInit --
+ *
+ * Initializes NL_BUF with buffer pointer and length.
+ * --------------------------------------------------------------------------
+ */
+VOID
+NlBufInit(PNL_BUFFER nlBuf, PCHAR base, UINT32 size)
+{
+ ASSERT(nlBuf);
+ nlBuf->head = nlBuf->tail = base;
+ nlBuf->bufLen = nlBuf->bufRemLen = size;
+}
+
+/*
+ * --------------------------------------------------------------------------
+ * NlBufDeInit --
+ *
+ * Resets the buffer variables to NULL.
+ * --------------------------------------------------------------------------
+ */
+VOID
+NlBufDeInit(PNL_BUFFER nlBuf)
+{
+ ASSERT(nlBuf);
+ nlBuf->head = nlBuf->tail = NULL;
+ nlBuf->bufLen = nlBuf->bufRemLen = 0;
+}
+
+/*
+ * --------------------------------------------------------------------------
+ * NlBufCopyAtTail --
+ *
+ * Copies the data to the tail end of the buffer.
+ * --------------------------------------------------------------------------
+ */
+BOOLEAN
+NlBufCopyAtTail(PNL_BUFFER nlBuf, PCHAR data, UINT32 len)
+{
+ BOOLEAN ret = TRUE;
+
+ ASSERT(nlBuf);
+
+ /* Check if we have enough space */
+ if (!NL_BUF_CAN_ADD(nlBuf, len, NL_BUF_TAIL_OFFSET(nlBuf))) {
+ ret = FALSE;
+ goto done;
+ }
+
+ _NlBufCopyAtTailUnsafe(nlBuf, data, len);
+
+done:
+ return ret;
+}
+
+/*
+ * --------------------------------------------------------------------------
+ * NlBufCopyAtHead --
+ *
+ * Copies the data to the head of the buffer.
+ * It can be seen as special case of NlBufCopyAtOffset with input offset zero.
+ * --------------------------------------------------------------------------
+ */
+BOOLEAN
+NlBufCopyAtHead(PNL_BUFFER nlBuf, PCHAR data, UINT32 len)
+{
+ BOOLEAN ret = TRUE;
+
+ ASSERT(nlBuf);
+
+ /* Check if we have enough space */
+ if (!NL_BUF_CAN_ADD(nlBuf, len, 0)) {
+ ret = FALSE;
+ goto done;
+ }
+
+ if (nlBuf->head == nlBuf->tail) {
+ /* same as inserting in tail */
+ _NlBufCopyAtTailUnsafe(nlBuf, data, len);
+ goto done;
+ }
+
+ _NlBufCopyAtOffsetUnsafe(nlBuf, data, len, 0);
+
+done:
+ return ret;
+}
+
+/*
+ * --------------------------------------------------------------------------
+ * NlBufCopyAtOffset --
+ *
+ * Inserts data at input offset in the buffer.
+ * If the offset is earlier then tail end then it first creates
+ * space of size input length at input offset by moving the existing
+ * data forward.
+ * --------------------------------------------------------------------------
+ */
+BOOLEAN
+NlBufCopyAtOffset(PNL_BUFFER nlBuf, PCHAR data, UINT32 len, UINT32 offset)
+{
+ PCHAR dest = NULL;
+ BOOLEAN ret = TRUE;
+
+ ASSERT(nlBuf);
+
+ /* Check if input offset is valid and has enough space */
+ if ((!NL_BUF_IS_VALID_OFFSET(nlBuf, offset)) ||
+ (!NL_BUF_CAN_ADD(nlBuf, len, offset))) {
+ ret = FALSE;
+ goto done;
+ }
+
+ dest = nlBuf->head + offset;
+
+ if (dest == nlBuf->tail) {
+ /* same as inserting in tail */
+ _NlBufCopyAtTailUnsafe(nlBuf, data, len);
+ goto done;
+ }
+
+ _NlBufCopyAtOffsetUnsafe(nlBuf, data, len, offset);
+
+done:
+ return ret;
+}
+
+/*
+ * --------------------------------------------------------------------------
+ * NlBufCopyAtTailUninit --
+ *
+ * Memsets the buffer portion of length len at tail end with zero.
+ * --------------------------------------------------------------------------
+ */
+PCHAR
+NlBufCopyAtTailUninit(PNL_BUFFER nlBuf, UINT32 len)
+{
+ PCHAR ret = NULL;
+
+ if ((NlBufCopyAtTail(nlBuf, NULL, len)) == FALSE) {
+ goto done;
+ }
+
+ ret = nlBuf->tail;
+
+done:
+ return ret;
+}
+
+/*
+ * --------------------------------------------------------------------------
+ * NlBufCopyAtHeadUninit --
+ *
+ * Memsets the buffer portion of length len at head with zero.
+ * --------------------------------------------------------------------------
+ */
+PCHAR
+NlBufCopyAtHeadUninit(PNL_BUFFER nlBuf, UINT32 len)
+{
+ PCHAR ret = NULL;
+
+ if ((NlBufCopyAtHead(nlBuf, NULL, len)) == FALSE) {
+ goto done;
+ }
+
+ ret = nlBuf->head;
+
+done:
+ return ret;
+}
+
+/*
+ * --------------------------------------------------------------------------
+ * NlBufCopyAtOffsetUninit --
+ *
+ * Memsets the buffer portion of length len at head with zero.
+ *
+ * If the offset is earlier then tail end then it first creates
+ * space of size input length at input offset by moving the existing
+ * data forward.
+ * --------------------------------------------------------------------------
+ */
+PCHAR
+NlBufCopyAtOffsetUninit(PNL_BUFFER nlBuf, UINT32 len, UINT32 offset)
+{
+ PCHAR ret = NULL;
+
+ if ((NlBufCopyAtOffset(nlBuf, NULL, len, offset)) == FALSE) {
+ goto done;
+ }
+
+ ret = nlBuf->head + offset;
+
+done:
+ return ret;
+}
+
+/*
+ * --------------------------------------------------------------------------
+ * NlBufAt --
+ *
+ * Returns pointer to buffer at input offset.
+ * bufLen is used to verify that expected data length
+ * is within valid boundaries.
+ * --------------------------------------------------------------------------
+ */
+PCHAR
+NlBufAt(PNL_BUFFER nlBuf, UINT32 offset, UINT32 bufLen)
+{
+ PCHAR ret = NULL;
+
+ ASSERT(nlBuf);
+
+ if ((!NL_BUF_IS_VALID_OFFSET(nlBuf, offset))) {
+ goto done;
+ }
+
+ if ((offset + bufLen) > NL_BUF_USED_SPACE(nlBuf)) {
+ goto done;
+ }
+
+ ret = nlBuf->head + offset;
+done:
+ return ret;
+}
+
+/* *_Unsafe functions does not do any validation. */
+
+/*
+ * --------------------------------------------------------------------------
+ * _NlBufCopyAtTailUnsafe --
+ *
+ * Helper function for NlBufCopyAtTail.
+ * --------------------------------------------------------------------------
+ */
+static __inline VOID
+_NlBufCopyAtTailUnsafe(PNL_BUFFER nlBuf, PCHAR data, UINT32 len)
+{
+ if (data) {
+ RtlCopyMemory(nlBuf->tail, data, len);
+ } else {
+ RtlZeroMemory(nlBuf->tail, len);
+ }
+
+ nlBuf->tail += len;
+ nlBuf->bufRemLen -= len;
+}
+
+/*
+ * --------------------------------------------------------------------------
+ * _NlBufCopyAtOffsetUnsafe --
+ *
+ * Helper function for NlBufCopyAtOffset.
+ * --------------------------------------------------------------------------
+ */
+static __inline VOID
+_NlBufCopyAtOffsetUnsafe(PNL_BUFFER nlBuf, PCHAR data, UINT32 len, UINT32 offset)
+{
+ PCHAR dest = NULL;
+
+ dest = nlBuf->head + offset;
+
+ RtlMoveMemory(dest+len, dest, NL_BUF_USED_SPACE(nlBuf) - offset);
+
+ if (data) {
+ RtlCopyMemory(dest, data, len);
+ } else {
+ RtlZeroMemory(dest, len);
+ }
+
+ nlBuf->tail += len;
+ nlBuf->bufRemLen -= len;
+}
diff --git a/datapath-windows/ovsext/Netlink/NetlinkBuf.h b/datapath-windows/ovsext/Netlink/NetlinkBuf.h
new file mode 100644
index 000000000..6a7a765d0
--- /dev/null
+++ b/datapath-windows/ovsext/Netlink/NetlinkBuf.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014 VMware, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __NETLINK_BUF_H_
+#define __NETLINK_BUF_H_ 1
+
+typedef struct _NL_BUF {
+ PCHAR head; /* start address of the buffer */
+ PCHAR tail; /* first empty byte of the buffer */
+ UINT32 bufLen; /* original length of buffer */
+ UINT32 bufRemLen; /* remaining length of buffer */
+} NL_BUFFER, *PNL_BUFFER;
+
+VOID NlBufInit(PNL_BUFFER nlBuf, PCHAR base, UINT32 size);
+VOID NlBufDeInit(PNL_BUFFER nlBuf);
+
+BOOLEAN NlBufCopyAtTail(PNL_BUFFER nlBuf, PCHAR data, UINT32 len);
+BOOLEAN NlBufCopyAtHead(PNL_BUFFER nlBuf, PCHAR data, UINT32 len);
+BOOLEAN NlBufCopyAtOffset(PNL_BUFFER nlBuf, PCHAR data,
+ UINT32 len, UINT32 offset);
+
+PCHAR NlBufCopyAtTailUninit(PNL_BUFFER nlBuf, UINT32 len);
+PCHAR NlBufCopyAtHeadUninit(PNL_BUFFER nlBuf, UINT32 len);
+PCHAR NlBufCopyAtOffsetUninit(PNL_BUFFER nlBuf, UINT32 len, UINT32 offset);
+
+PCHAR NlBufAt(PNL_BUFFER nlBuf, UINT32 offset, UINT32 len);
+
+#endif /* __NETLINK_BUF_H_ */
diff --git a/datapath-windows/ovsext/ovsext.vcxproj b/datapath-windows/ovsext/ovsext.vcxproj
index a5464d440..a9183618c 100644
--- a/datapath-windows/ovsext/ovsext.vcxproj
+++ b/datapath-windows/ovsext/ovsext.vcxproj
@@ -83,6 +83,7 @@
<ClInclude Include="IpHelper.h" />
<ClInclude Include="Jhash.h" />
<ClInclude Include="Netlink/Netlink.h" />
+ <ClInclude Include="Netlink/NetlinkBuf.h" />
<ClInclude Include="Netlink/NetlinkProto.h" />
<ClInclude Include="NetProto.h" />
<ClInclude Include="Oid.h" />
@@ -139,6 +140,7 @@
<ClCompile Include="IpHelper.c" />
<ClCompile Include="Jhash.c" />
<ClCompile Include="Netlink/Netlink.c" />
+ <ClCompile Include="Netlink/NetlinkBuf.c" />
<ClCompile Include="Datapath.c" />
<ClCompile Include="Oid.c" />
<ClCompile Include="PacketIO.c" />