#pragma warning( push )
#pragma warning( disable:4127 )
-extern PNDIS_SPIN_LOCK gOvsCtrlLock;
extern POVS_SWITCH_CONTEXT gOvsSwitchContext;
extern UINT64 ovsTimeIncrementPerTick;
UINT32 *replyLen);
static NTSTATUS _MapFlowInfoToNl(PNL_BUFFER nlBuf,
OvsFlowInfo *flowInfo);
-static NTSTATUS _MapFlowKeyToNlKey(PNL_BUFFER nlBuf,
- OvsFlowKey *flowKey);
-static NTSTATUS _MapFlowTunKeyToNlKey(PNL_BUFFER nlBuf,
- OvsIPv4TunnelKey *tunKey);
static NTSTATUS _MapFlowStatsToNlStats(PNL_BUFFER nlBuf,
OvsFlowStats *flowStats);
static NTSTATUS _MapFlowActionToNlAction(PNL_BUFFER nlBuf,
/* Flow family related netlink policies */
/* For Parsing attributes in FLOW_* commands */
-static const NL_POLICY nlFlowPolicy[] = {
+const NL_POLICY nlFlowPolicy[] = {
[OVS_FLOW_ATTR_KEY] = {.type = NL_A_NESTED, .optional = FALSE},
[OVS_FLOW_ATTR_MASK] = {.type = NL_A_NESTED, .optional = TRUE},
[OVS_FLOW_ATTR_ACTIONS] = {.type = NL_A_NESTED, .optional = TRUE},
* Some of the attributes like OVS_KEY_ATTR_RECIRC_ID
* & OVS_KEY_ATTR_MPLS are not supported yet. */
-static const NL_POLICY nlFlowKeyPolicy[] = {
+const NL_POLICY nlFlowKeyPolicy[] = {
[OVS_KEY_ATTR_ENCAP] = {.type = NL_A_VAR_LEN, .optional = TRUE},
[OVS_KEY_ATTR_PRIORITY] = {.type = NL_A_UNSPEC, .minLen = 4,
.maxLen = 4, .optional = TRUE},
[OVS_KEY_ATTR_ETHERNET] = {.type = NL_A_UNSPEC,
.minLen = sizeof(struct ovs_key_ethernet),
.maxLen = sizeof(struct ovs_key_ethernet),
- .optional = FALSE},
+ .optional = TRUE},
[OVS_KEY_ATTR_VLAN] = {.type = NL_A_UNSPEC, .minLen = 2,
.maxLen = 2, .optional = TRUE},
[OVS_KEY_ATTR_ETHERTYPE] = {.type = NL_A_UNSPEC, .minLen = 2,
};
/* For Parsing nested OVS_KEY_ATTR_TUNNEL attributes */
-static const NL_POLICY nlFlowTunnelKeyPolicy[] = {
+const NL_POLICY nlFlowTunnelKeyPolicy[] = {
[OVS_TUNNEL_KEY_ATTR_ID] = {.type = NL_A_UNSPEC, .minLen = 8,
.maxLen = 8, .optional = TRUE},
[OVS_TUNNEL_KEY_ATTR_IPV4_SRC] = {.type = NL_A_UNSPEC, .minLen = 4,
};
/* For Parsing nested OVS_FLOW_ATTR_ACTIONS attributes */
-static const NL_POLICY nlFlowActionPolicy[] = {
+const NL_POLICY nlFlowActionPolicy[] = {
[OVS_ACTION_ATTR_OUTPUT] = {.type = NL_A_UNSPEC, .minLen = sizeof(UINT32),
.maxLen = sizeof(UINT32), .optional = TRUE},
[OVS_ACTION_ATTR_USERSPACE] = {.type = NL_A_VAR_LEN, .optional = TRUE},
UINT32 *replyLen)
{
NTSTATUS rc = STATUS_SUCCESS;
+ BOOLEAN ok;
POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;
POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer;
PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
OvsFlowStats stats;
struct ovs_flow_stats replyStats;
NL_ERROR nlError = NL_ERROR_SUCCESS;
-
NL_BUFFER nlBuf;
RtlZeroMemory(&mappedFlow, sizeof(OvsFlowPut));
RtlZeroMemory(&stats, sizeof(stats));
RtlZeroMemory(&replyStats, sizeof(replyStats));
- *replyLen = 0;
-
if (!(usrParamsCtx->outputBuffer)) {
/* No output buffer */
rc = STATUS_INVALID_BUFFER_SIZE;
/* FLOW_DEL command w/o any key input is a flush case. */
if ((genlMsgHdr->cmd == OVS_FLOW_CMD_DEL) &&
(!(nlAttrs[OVS_FLOW_ATTR_KEY]))) {
+
rc = OvsFlushFlowIoctl(ovsHdr->dp_ifindex);
- goto done;
+
+ if (rc == STATUS_SUCCESS) {
+ /* XXX: refactor this code. */
+ /* So far so good. Prepare the reply for userspace */
+ NlBufInit(&nlBuf, usrParamsCtx->outputBuffer,
+ usrParamsCtx->outputLength);
+
+ /* Prepare nl Msg headers */
+ ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,
+ nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
+ genlMsgHdr->cmd, OVS_FLOW_VERSION,
+ ovsHdr->dp_ifindex);
+ if (ok) {
+ *replyLen = msgOut->nlMsg.nlmsgLen;
+ } else {
+ rc = STATUS_INVALID_BUFFER_SIZE;
+ }
+ }
+
+ goto done;
}
if ((rc = _MapNlToFlowPut(msgIn, nlAttrs[OVS_FLOW_ATTR_KEY],
rc = OvsPutFlowIoctl(&mappedFlow, sizeof (struct OvsFlowPut),
&stats);
if (rc != STATUS_SUCCESS) {
- OVS_LOG_ERROR("OvsFlowPut failed.");
+ OVS_LOG_ERROR("OvsPutFlowIoctl failed.");
goto done;
}
usrParamsCtx->outputLength);
/* Prepare nl Msg headers */
- rc = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,
+ ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,
nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
genlMsgHdr->cmd, OVS_FLOW_VERSION,
ovsHdr->dp_ifindex);
- ASSERT(rc);
+ if (!ok) {
+ rc = STATUS_INVALID_BUFFER_SIZE;
+ goto done;
+ } else {
+ rc = STATUS_SUCCESS;
+ }
/* Append OVS_FLOW_ATTR_STATS attribute */
if (!NlMsgPutTailUnspec(&nlBuf, OVS_FLOW_ATTR_STATS,
done:
- if ((nlError != NL_ERROR_SUCCESS) &&
- (usrParamsCtx->outputBuffer)) {
+ if (nlError != NL_ERROR_SUCCESS) {
POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
usrParamsCtx->outputBuffer;
- BuildErrorMsg(msgIn, msgError, nlError);
+ NlBuildErrorMsg(msgIn, msgError, nlError);
*replyLen = msgError->nlMsg.nlmsgLen;
+ rc = STATUS_SUCCESS;
}
return rc;
OvsFlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
UINT32 *replyLen)
{
- NTSTATUS rc = STATUS_SUCCESS;
+ NTSTATUS status = STATUS_SUCCESS;
NL_ERROR nlError = NL_ERROR_SUCCESS;
POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;
- *replyLen = 0;
-
- if (!(usrParamsCtx->outputBuffer)) {
- /* No output buffer */
- rc = STATUS_INVALID_BUFFER_SIZE;
- goto done;
- }
-
if (usrParamsCtx->devOp == OVS_TRANSACTION_DEV_OP) {
- rc = _FlowNlGetCmdHandler(usrParamsCtx, replyLen);
+ status = _FlowNlGetCmdHandler(usrParamsCtx, replyLen);
+
+ /* No trasanctional errors as of now.
+ * If we have something then we need to convert rc to
+ * nlError. */
+ if ((nlError != NL_ERROR_SUCCESS) &&
+ (usrParamsCtx->outputBuffer)) {
+ POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
+ usrParamsCtx->outputBuffer;
+ NlBuildErrorMsg(msgIn, msgError, nlError);
+ *replyLen = msgError->nlMsg.nlmsgLen;
+ status = STATUS_SUCCESS;
+ goto done;
+ }
} else {
- rc = _FlowNlDumpCmdHandler(usrParamsCtx, replyLen);
- }
-
- if ((nlError != NL_ERROR_SUCCESS) &&
- (usrParamsCtx->outputBuffer)) {
- POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
- usrParamsCtx->outputBuffer;
- BuildErrorMsg(msgIn, msgError, nlError);
- *replyLen = msgError->nlMsg.nlmsgLen;
+ status = _FlowNlDumpCmdHandler(usrParamsCtx, replyLen);
}
done:
- return rc;
+ return status;
}
/*
UINT32 *replyLen)
{
NTSTATUS rc = STATUS_SUCCESS;
- POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)
- (usrParamsCtx->ovsInstance);
- POVS_MESSAGE msgIn = instance->dumpState.ovsMsg;
+ POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;
PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
POVS_HDR ovsHdr = &(msgIn->ovsHdr);
PNL_MSG_HDR nlMsgOutHdr = NULL;
RtlZeroMemory(&getOutput, sizeof(OvsFlowGetOutput));
UINT32 keyAttrOffset = 0;
UINT32 tunnelKeyAttrOffset = 0;
-
- *replyLen = 0;
+ BOOLEAN ok;
if (usrParamsCtx->inputLength > usrParamsCtx->outputLength) {
/* Should not be the case.
/* Input already has all the attributes for the flow key.
* Lets copy the values back. */
- RtlCopyMemory(usrParamsCtx->outputBuffer, usrParamsCtx->inputBuffer,
- usrParamsCtx->inputLength);
+ ok = NlMsgPutTail(&nlBuf, (PCHAR)(usrParamsCtx->inputBuffer),
+ usrParamsCtx->inputLength);
+ if (!ok) {
+ OVS_LOG_ERROR("Could not copy the data to the buffer tail");
+ goto done;
+ }
rc = _MapFlowStatsToNlStats(&nlBuf, &((getOutput.info).stats));
if (rc != STATUS_SUCCESS) {
/*
*----------------------------------------------------------------------------
* _FlowNlDumpCmdHandler --
- * Handler for OVS_FLOW_CMD_GET command.
+ * Handler for OVS_FLOW_CMD_DUMP command.
*----------------------------------------------------------------------------
*/
NTSTATUS
/* Done with Dump, send NLMSG_DONE */
if (!(dumpOutput.n)) {
+ BOOLEAN ok;
+
OVS_LOG_INFO("Dump Done");
nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, NlBufSize(&nlBuf), 0));
- rc = NlFillNlHdr(&nlBuf, NLMSG_DONE, NLM_F_MULTI,
+ ok = NlFillNlHdr(&nlBuf, NLMSG_DONE, NLM_F_MULTI,
nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid);
- if (rc != STATUS_SUCCESS) {
+ if (!ok) {
+ rc = STATUS_INVALID_BUFFER_SIZE;
OVS_LOG_ERROR("Unable to prepare DUMP_DONE reply.");
break;
+ } else {
+ rc = STATUS_SUCCESS;
}
NlMsgAlignSize(nlMsgOutHdr);
FreeUserDumpState(instance);
break;
} else {
+ BOOLEAN ok;
hdrOffset = NlBufSize(&nlBuf);
nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, hdrOffset, 0));
/* Netlink header */
- rc = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, NLM_F_MULTI,
+ ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, NLM_F_MULTI,
nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
genlMsgHdr->cmd, genlMsgHdr->version,
ovsHdr->dp_ifindex);
- if (rc != STATUS_SUCCESS) {
+ if (!ok) {
/* Reset rc to success so that we can
* send already added messages to user space. */
rc = STATUS_SUCCESS;
{
NTSTATUS rc = STATUS_SUCCESS;
- rc = _MapFlowKeyToNlKey(nlBuf, &(flowInfo->key));
+ rc = MapFlowKeyToNlKey(nlBuf, &(flowInfo->key), OVS_FLOW_ATTR_KEY,
+ OVS_KEY_ATTR_TUNNEL);
if (rc != STATUS_SUCCESS) {
goto done;
}
/*
*----------------------------------------------------------------------------
- * _MapFlowKeyToNlKey --
- * Maps OvsFlowKey to OVS_FLOW_ATTR_KEY attribute.
+ * MapFlowKeyToNlKey --
+ * Maps OvsFlowKey to OVS_FLOW_ATTR_KEY attribute.
*----------------------------------------------------------------------------
*/
-static NTSTATUS
-_MapFlowKeyToNlKey(PNL_BUFFER nlBuf, OvsFlowKey *flowKey)
+NTSTATUS
+MapFlowKeyToNlKey(PNL_BUFFER nlBuf,
+ OvsFlowKey *flowKey,
+ UINT16 keyType,
+ UINT16 tunKeyType)
{
NTSTATUS rc = STATUS_SUCCESS;
struct ovs_key_ethernet ethKey;
UINT32 offset = 0;
- offset = NlMsgStartNested(nlBuf, OVS_FLOW_ATTR_KEY);
+ offset = NlMsgStartNested(nlBuf, keyType);
if (!offset) {
/* Starting the nested attribute failed. */
rc = STATUS_UNSUCCESSFUL;
}
if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_ETHERTYPE,
- htons(flowKey->l2.dlType))) {
+ flowKey->l2.dlType)) {
rc = STATUS_UNSUCCESSFUL;
goto done;
}
}
/* ==== L3 + L4 ==== */
- switch (flowKey->l2.dlType) {
+ switch (ntohs(flowKey->l2.dlType)) {
case ETH_TYPE_IPV4: {
IpKey *ipv4FlowPutKey = &(flowKey->ipKey);
rc = _MapFlowIpv4KeyToNlKey(nlBuf, ipv4FlowPutKey);
}
if (flowKey->tunKey.dst) {
- rc = _MapFlowTunKeyToNlKey(nlBuf, &(flowKey->tunKey));
+ rc = MapFlowTunKeyToNlKey(nlBuf, &(flowKey->tunKey),
+ tunKeyType);
if (rc != STATUS_SUCCESS) {
goto done;
}
/*
*----------------------------------------------------------------------------
- * _MapFlowTunKeyToNlKey --
- * Maps OvsIPv4TunnelKey to OVS_TUNNEL_KEY_ATTR_ID attribute.
+ * MapFlowTunKeyToNlKey --
+ * Maps OvsIPv4TunnelKey to OVS_TUNNEL_KEY_ATTR_ID attribute.
*----------------------------------------------------------------------------
*/
-static NTSTATUS
-_MapFlowTunKeyToNlKey(PNL_BUFFER nlBuf, OvsIPv4TunnelKey *tunKey)
+NTSTATUS
+MapFlowTunKeyToNlKey(PNL_BUFFER nlBuf,
+ OvsIPv4TunnelKey *tunKey,
+ UINT16 tunKeyType)
{
NTSTATUS rc = STATUS_SUCCESS;
UINT32 offset = 0;
- offset = NlMsgStartNested(nlBuf, OVS_KEY_ATTR_TUNNEL);
+ offset = NlMsgStartNested(nlBuf, tunKeyType);
if (!offset) {
/* Starting the nested attribute failed. */
rc = STATUS_UNSUCCESSFUL;
RtlCopyMemory(&(arpKey.arp_sha), arpFlowPutKey->arpSha, ETH_ADDR_LEN);
RtlCopyMemory(&(arpKey.arp_tha), arpFlowPutKey->arpTha, ETH_ADDR_LEN);
- arpKey.arp_op = arpFlowPutKey->nwProto;
+ /*
+ * Flow_Extract() stores 'nwProto' in host order for ARP since 'nwProto' is
+ * 1 byte field and the ARP opcode is 2 bytes, and all of the kernel code
+ * understand this while looking at an ARP key.
+ * While we pass up the ARP key to userspace, convert from host order to
+ * network order. Likewise, when processing an ARP key from userspace,
+ * convert from network order to host order.
+ *
+ * It is important to note that the flow table stores the ARP opcode field
+ * in host order.
+ */
+ arpKey.arp_op = htons(arpFlowPutKey->nwProto);
if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ARP,
(PCHAR)(&arpKey),
(keyAttrs[OVS_KEY_ATTR_TUNNEL])
- (PCHAR)nlMsgHdr);
- OVS_LOG_ERROR("Parse Flow Tunnel Key Policy");
-
/* Get tunnel keys attributes */
if ((NlAttrParseNested(nlMsgHdr, tunnelKeyAttrOffset,
NlAttrLen(keyAttrs[OVS_KEY_ATTR_TUNNEL]),
PNL_ATTR *tunnelAttrs,
OvsFlowKey *destKey)
{
- const struct ovs_key_ethernet *eth_key;
-
_MapTunAttrToFlowPut(keyAttrs, tunnelAttrs, destKey);
/* ===== L2 headers ===== */
destKey->l2.inPort = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_IN_PORT]);
- eth_key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ETHERNET]);
- RtlCopyMemory(destKey->l2.dlSrc, eth_key->eth_src, ETH_ADDR_LEN);
- RtlCopyMemory(destKey->l2.dlDst, eth_key->eth_dst, ETH_ADDR_LEN);
- destKey->l2.dlType = ntohs((NlAttrGetU16(keyAttrs
- [OVS_KEY_ATTR_ETHERTYPE])));
+ if (keyAttrs[OVS_KEY_ATTR_ETHERNET]) {
+ const struct ovs_key_ethernet *eth_key;
+ eth_key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ETHERNET]);
+ RtlCopyMemory(destKey->l2.dlSrc, eth_key->eth_src, ETH_ADDR_LEN);
+ RtlCopyMemory(destKey->l2.dlDst, eth_key->eth_dst, ETH_ADDR_LEN);
+ }
+
+ /* TODO: Ideally ETHERTYPE should not be optional.
+ * But during vswitchd bootup we are seeing FLOW_ADD
+ * requests with no ETHERTYPE attributes.
+ * Need to verify this. */
+ if (keyAttrs[OVS_KEY_ATTR_ETHERTYPE]) {
+ destKey->l2.dlType = (NlAttrGetU16(keyAttrs
+ [OVS_KEY_ATTR_ETHERTYPE]));
+ }
if (keyAttrs[OVS_KEY_ATTR_VLAN]) {
- destKey->l2.vlanTci = NlAttrGetU16(keyAttrs
- [OVS_KEY_ATTR_VLAN]);
+ destKey->l2.vlanTci = NlAttrGetU16(keyAttrs[OVS_KEY_ATTR_VLAN]);
}
/* ==== L3 + L4. ==== */
destKey->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + OVS_L2_KEY_SIZE
- destKey->l2.offset;
- switch (destKey->l2.dlType) {
+ switch (ntohs(destKey->l2.dlType)) {
case ETH_TYPE_IPV4: {
if (keyAttrs[OVS_KEY_ATTR_IPV4]) {
}
case ETH_TYPE_ARP:
case ETH_TYPE_RARP: {
- ArpKey *arpFlowPutKey = &destKey->arpKey;
- const struct ovs_key_arp *arpKey;
- arpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ARP]);
+ if (keyAttrs[OVS_KEY_ATTR_ARP]) {
+ ArpKey *arpFlowPutKey = &destKey->arpKey;
+ const struct ovs_key_arp *arpKey;
- arpFlowPutKey->nwSrc = arpKey->arp_sip;
- arpFlowPutKey->nwDst = arpKey->arp_tip;
+ arpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ARP]);
- RtlCopyMemory(arpFlowPutKey->arpSha, arpKey->arp_sha, ETH_ADDR_LEN);
- RtlCopyMemory(arpFlowPutKey->arpTha, arpKey->arp_tha, ETH_ADDR_LEN);
- arpFlowPutKey->nwProto = (UINT8)(arpKey->arp_op);
- arpFlowPutKey->pad[0] = 0;
- arpFlowPutKey->pad[1] = 0;
- arpFlowPutKey->pad[2] = 0;
- destKey->l2.keyLen += OVS_ARP_KEY_SIZE;
- break;
+ arpFlowPutKey->nwSrc = arpKey->arp_sip;
+ arpFlowPutKey->nwDst = arpKey->arp_tip;
+
+ RtlCopyMemory(arpFlowPutKey->arpSha, arpKey->arp_sha, ETH_ADDR_LEN);
+ RtlCopyMemory(arpFlowPutKey->arpTha, arpKey->arp_tha, ETH_ADDR_LEN);
+ /* Kernel datapath assumes 'arpFlowPutKey->nwProto' to be in host
+ * order. */
+ arpFlowPutKey->nwProto = (UINT8)ntohs((arpKey->arp_op));
+ arpFlowPutKey->pad[0] = 0;
+ arpFlowPutKey->pad[1] = 0;
+ arpFlowPutKey->pad[2] = 0;
+ destKey->l2.keyLen += OVS_ARP_KEY_SIZE;
+ break;
+ }
}
}
}
}
DeleteAllFlows(datapath);
- OvsFreeMemory(datapath->flowTable);
+ OvsFreeMemoryWithTag(datapath->flowTable, OVS_FLOW_POOL_TAG);
datapath->flowTable = NULL;
+
+ if (datapath->lock == NULL) {
+ return NDIS_STATUS_SUCCESS;
+ }
+
NdisFreeRWLock(datapath->lock);
return NDIS_STATUS_SUCCESS;
PLIST_ENTRY bucket;
int i;
- datapath->flowTable = OvsAllocateMemory(OVS_FLOW_TABLE_SIZE *
- sizeof (LIST_ENTRY));
+ datapath->flowTable = OvsAllocateMemoryWithTag(
+ OVS_FLOW_TABLE_SIZE * sizeof(LIST_ENTRY), OVS_FLOW_POOL_TAG);
if (!datapath->flowTable) {
return NDIS_STATUS_RESOURCES;
}
}
datapath->lock = NdisAllocateRWLock(switchContext->NdisFilterHandle);
+ if (!datapath->lock) {
+ return NDIS_STATUS_RESOURCES;
+ }
+
return NDIS_STATUS_SUCCESS;
}
{
OvsFlow *f = *flow;
*flow = NULL;
- UNREFERENCED_PARAMETER(datapath);
ASSERT(datapath->nFlows);
datapath->nFlows--;
FreeFlow(OvsFlow *flow)
{
ASSERT(flow);
- OvsFreeMemory(flow);
+ OvsFreeMemoryWithTag(flow, OVS_FLOW_POOL_TAG);
}
NTSTATUS
BOOLEAN findNextNonEmpty = FALSE;
dpNo = dumpInput->dpNo;
- NdisAcquireSpinLock(gOvsCtrlLock);
- if (gOvsSwitchContext == NULL ||
- gOvsSwitchContext->dpNo != dpNo) {
+ if (gOvsSwitchContext->dpNo != dpNo) {
status = STATUS_INVALID_PARAMETER;
- goto unlock;
+ goto exit;
}
rowIndex = dumpInput->position[0];
if (rowIndex >= OVS_FLOW_TABLE_SIZE) {
dumpOutput->n = 0;
*replyLen = sizeof(*dumpOutput);
- goto unlock;
+ goto exit;
}
columnIndex = dumpInput->position[1];
datapath = &gOvsSwitchContext->datapath;
ASSERT(datapath);
- ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
- OvsAcquireDatapathRead(datapath, &dpLockState, TRUE);
+ OvsAcquireDatapathRead(datapath, &dpLockState, FALSE);
head = &datapath->flowTable[rowIndex];
node = head->Flink;
dp_unlock:
OvsReleaseDatapath(datapath, &dpLockState);
-unlock:
- NdisReleaseSpinLock(gOvsCtrlLock);
+exit:
return status;
}
-NTSTATUS
-OvsDumpFlowIoctl(PVOID inputBuffer,
- UINT32 inputLength,
- PVOID outputBuffer,
- UINT32 outputLength,
- UINT32 *replyLen)
-{
- OvsFlowDumpOutput *dumpOutput = (OvsFlowDumpOutput *)outputBuffer;
- OvsFlowDumpInput *dumpInput = (OvsFlowDumpInput *)inputBuffer;
-
- if (inputBuffer == NULL || outputBuffer == NULL) {
- return STATUS_INVALID_PARAMETER;
- }
-
- if ((inputLength != sizeof(OvsFlowDumpInput))
- || (outputLength != sizeof *dumpOutput + dumpInput->actionsLen)) {
- return STATUS_INFO_LENGTH_MISMATCH;
- }
-
- return OvsDoDumpFlows(dumpInput, dumpOutput, replyLen);
-}
-
static NTSTATUS
ReportFlowInfo(OvsFlow *flow,
UINT32 getFlags,
}
dpNo = put->dpNo;
- NdisAcquireSpinLock(gOvsCtrlLock);
- if (gOvsSwitchContext == NULL ||
- gOvsSwitchContext->dpNo != dpNo) {
+ if (gOvsSwitchContext->dpNo != dpNo) {
status = STATUS_INVALID_PARAMETER;
- goto unlock;
+ goto exit;
}
datapath = &gOvsSwitchContext->datapath;
ASSERT(datapath);
- ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
- OvsAcquireDatapathWrite(datapath, &dpLockState, TRUE);
+ OvsAcquireDatapathWrite(datapath, &dpLockState, FALSE);
status = HandleFlowPut(put, datapath, stats);
OvsReleaseDatapath(datapath, &dpLockState);
-unlock:
- NdisReleaseSpinLock(gOvsCtrlLock);
+exit:
return status;
}
status = OvsPrepareFlow(&KernelFlow, put, hash);
if (status != STATUS_SUCCESS) {
- FreeFlow(KernelFlow);
return STATUS_UNSUCCESSFUL;
}
RemoveFlow(datapath, &KernelFlow);
}
} else {
- return STATUS_UNSUCCESSFUL;
+ /* Return success if an identical flow already exists. */
+ /* XXX: should we return EEXIST in a netlink error? */
+ return STATUS_SUCCESS;
}
}
}
do {
*flow = localFlow =
- OvsAllocateMemory(sizeof(OvsFlow) + put->actionsLen);
+ OvsAllocateMemoryWithTag(sizeof(OvsFlow) + put->actionsLen,
+ OVS_FLOW_POOL_TAG);
if (localFlow == NULL) {
status = STATUS_NO_MEMORY;
break;
}
dpNo = getInput->dpNo;
- NdisAcquireSpinLock(gOvsCtrlLock);
- if (gOvsSwitchContext == NULL ||
- gOvsSwitchContext->dpNo != dpNo) {
+ if (gOvsSwitchContext->dpNo != dpNo) {
status = STATUS_INVALID_PARAMETER;
- goto unlock;
+ goto exit;
}
datapath = &gOvsSwitchContext->datapath;
ASSERT(datapath);
- ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
- OvsAcquireDatapathRead(datapath, &dpLockState, TRUE);
+ OvsAcquireDatapathRead(datapath, &dpLockState, FALSE);
flow = OvsLookupFlow(datapath, &getInput->key, &hash, FALSE);
if (!flow) {
status = STATUS_INVALID_PARAMETER;
dp_unlock:
OvsReleaseDatapath(datapath, &dpLockState);
-unlock:
- NdisReleaseSpinLock(gOvsCtrlLock);
+exit:
return status;
}
OVS_DATAPATH *datapath = NULL;
LOCK_STATE_EX dpLockState;
- NdisAcquireSpinLock(gOvsCtrlLock);
- if (gOvsSwitchContext == NULL ||
- gOvsSwitchContext->dpNo != dpNo) {
+ if (gOvsSwitchContext->dpNo != dpNo) {
status = STATUS_INVALID_PARAMETER;
- goto unlock;
+ goto exit;
}
datapath = &gOvsSwitchContext->datapath;
ASSERT(datapath);
- ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
- OvsAcquireDatapathWrite(datapath, &dpLockState, TRUE);
+ OvsAcquireDatapathWrite(datapath, &dpLockState, FALSE);
DeleteAllFlows(datapath);
OvsReleaseDatapath(datapath, &dpLockState);
-unlock:
- NdisReleaseSpinLock(gOvsCtrlLock);
+exit:
return status;
}
+UINT32
+OvsFlowKeyAttrSize(void)
+{
+ return NlAttrTotalSize(4) /* OVS_KEY_ATTR_PRIORITY */
+ + NlAttrTotalSize(0) /* OVS_KEY_ATTR_TUNNEL */
+ + OvsTunKeyAttrSize()
+ + NlAttrTotalSize(4) /* OVS_KEY_ATTR_IN_PORT */
+ + NlAttrTotalSize(4) /* OVS_KEY_ATTR_SKB_MARK */
+ + NlAttrTotalSize(4) /* OVS_KEY_ATTR_DP_HASH */
+ + NlAttrTotalSize(4) /* OVS_KEY_ATTR_RECIRC_ID */
+ + NlAttrTotalSize(12) /* OVS_KEY_ATTR_ETHERNET */
+ + NlAttrTotalSize(2) /* OVS_KEY_ATTR_ETHERTYPE */
+ + NlAttrTotalSize(4) /* OVS_KEY_ATTR_VLAN */
+ + NlAttrTotalSize(0) /* OVS_KEY_ATTR_ENCAP */
+ + NlAttrTotalSize(2) /* OVS_KEY_ATTR_ETHERTYPE */
+ + NlAttrTotalSize(40) /* OVS_KEY_ATTR_IPV6 */
+ + NlAttrTotalSize(2) /* OVS_KEY_ATTR_ICMPV6 */
+ + NlAttrTotalSize(28); /* OVS_KEY_ATTR_ND */
+}
+
+UINT32
+OvsTunKeyAttrSize(void)
+{
+ /* Whenever adding new OVS_TUNNEL_KEY_ FIELDS, we should consider
+ * updating this function.
+ */
+ return NlAttrTotalSize(8) /* OVS_TUNNEL_KEY_ATTR_ID */
+ + NlAttrTotalSize(4) /* OVS_TUNNEL_KEY_ATTR_IPV4_SRC */
+ + NlAttrTotalSize(4) /* OVS_TUNNEL_KEY_ATTR_IPV4_DST */
+ + NlAttrTotalSize(1) /* OVS_TUNNEL_KEY_ATTR_TOS */
+ + NlAttrTotalSize(1) /* OVS_TUNNEL_KEY_ATTR_TTL */
+ + NlAttrTotalSize(0) /* OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT */
+ + NlAttrTotalSize(0) /* OVS_TUNNEL_KEY_ATTR_CSUM */
+ + NlAttrTotalSize(0) /* OVS_TUNNEL_KEY_ATTR_OAM */
+ + NlAttrTotalSize(256) /* OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS */
+ + NlAttrTotalSize(2) /* OVS_TUNNEL_KEY_ATTR_TP_SRC */
+ + NlAttrTotalSize(2); /* OVS_TUNNEL_KEY_ATTR_TP_DST */
+}
+
#pragma warning( pop )