diff options
-rw-r--r-- | datapath-windows/automake.mk | 2 | ||||
-rw-r--r-- | datapath-windows/ovsext/Netlink/NetlinkBuf.c | 349 | ||||
-rw-r--r-- | datapath-windows/ovsext/Netlink/NetlinkBuf.h | 41 | ||||
-rw-r--r-- | datapath-windows/ovsext/ovsext.vcxproj | 2 |
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" /> |