mirror of
https://github.com/openvswitch/ovs
synced 2025-08-22 09:58:01 +00:00
datapath-windows: support meter action initial version
This patch implemented meter action, currently, meter only support drop method and only support one band. The overall implementation is, when a packet comes in, it will first lookup meter according to the meter id, then get the band->rates and delta time since last access the same meter from the meter struct. Add the multiply result(band->rates * delta_time) to bucket, finally bucket minus the packet size, if the result larger than zero, allow the packet go through, otherwise deny the packet go through. Test case: 1. Setting the size meter size 3M, then the bandwidth was limit around 3M; ovs-ofctl -O OpenFlow13 add-meter br-test meter=2,kbps,\ band=type=drop,rate=3000 ovs-ofctl add-flow br-test "table=0,priority=1,ip \ actions=meter:2,normal" -O OpenFlow13 2. Setting the meter size 8M, then the bandwidth was limit around 8M; ovs-ofctl -O OpenFlow13 add-meter br-test meter=2,\ kbps,band=type=drop,rate=8000 ovs-ofctl add-flow br-test "table=0,priority=1,ip\ actions=meter:2,normal" -O OpenFlow13 Signed-off-by: ldejing <ldejing@vmware.com> Signed-off-by: Alin-Gabriel Serdean <aserdean@ovn.org>
This commit is contained in:
parent
7af5c33c16
commit
b26015c33f
@ -44,6 +44,8 @@ EXTRA_DIST += \
|
|||||||
datapath-windows/ovsext/Jhash.c \
|
datapath-windows/ovsext/Jhash.c \
|
||||||
datapath-windows/ovsext/Jhash.h \
|
datapath-windows/ovsext/Jhash.h \
|
||||||
datapath-windows/ovsext/Mpls.h \
|
datapath-windows/ovsext/Mpls.h \
|
||||||
|
datapath-windows/ovsext/Meter.c \
|
||||||
|
datapath-windows/ovsext/Meter.h \
|
||||||
datapath-windows/ovsext/NetProto.h \
|
datapath-windows/ovsext/NetProto.h \
|
||||||
datapath-windows/ovsext/Netlink/Netlink.c \
|
datapath-windows/ovsext/Netlink/Netlink.c \
|
||||||
datapath-windows/ovsext/Netlink/Netlink.h \
|
datapath-windows/ovsext/Netlink/Netlink.h \
|
||||||
|
@ -74,6 +74,9 @@
|
|||||||
#define OVS_WIN_NL_CT_FAMILY_ID (NLMSG_MIN_TYPE + 7)
|
#define OVS_WIN_NL_CT_FAMILY_ID (NLMSG_MIN_TYPE + 7)
|
||||||
#define OVS_WIN_NL_CTLIMIT_FAMILY_ID (NLMSG_MIN_TYPE + 8)
|
#define OVS_WIN_NL_CTLIMIT_FAMILY_ID (NLMSG_MIN_TYPE + 8)
|
||||||
|
|
||||||
|
/* Meter Family */
|
||||||
|
#define OVS_WIN_NL_METER_FAMILY_ID (NLMSG_MIN_TYPE + 9)
|
||||||
|
|
||||||
#define OVS_WIN_NL_INVALID_MCGRP_ID 0
|
#define OVS_WIN_NL_INVALID_MCGRP_ID 0
|
||||||
#define OVS_WIN_NL_MCGRP_START_ID 100
|
#define OVS_WIN_NL_MCGRP_START_ID 100
|
||||||
#define OVS_WIN_NL_VPORT_MCGRP_ID (OVS_WIN_NL_MCGRP_START_ID + 1)
|
#define OVS_WIN_NL_VPORT_MCGRP_ID (OVS_WIN_NL_MCGRP_START_ID + 1)
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include "Flow.h"
|
#include "Flow.h"
|
||||||
#include "Gre.h"
|
#include "Gre.h"
|
||||||
#include "Jhash.h"
|
#include "Jhash.h"
|
||||||
|
#include "Meter.h"
|
||||||
#include "Mpls.h"
|
#include "Mpls.h"
|
||||||
#include "NetProto.h"
|
#include "NetProto.h"
|
||||||
#include "Offload.h"
|
#include "Offload.h"
|
||||||
@ -2503,6 +2504,15 @@ OvsDoExecuteActions(POVS_SWITCH_CONTEXT switchContext,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case OVS_ACTION_ATTR_METER: {
|
||||||
|
if (OvsMeterExecute(&ovsFwdCtx, NlAttrGetU32(a))) {
|
||||||
|
OVS_LOG_INFO("Drop packet");
|
||||||
|
dropReason = L"Ovs-meter exceed max rate";
|
||||||
|
goto dropit;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
case OVS_ACTION_ATTR_SAMPLE:
|
case OVS_ACTION_ATTR_SAMPLE:
|
||||||
{
|
{
|
||||||
if (ovsFwdCtx.destPortsSizeOut > 0 || ovsFwdCtx.tunnelTxNic != NULL
|
if (ovsFwdCtx.destPortsSizeOut > 0 || ovsFwdCtx.tunnelTxNic != NULL
|
||||||
|
@ -100,7 +100,11 @@ NetlinkCmdHandler OvsGetNetdevCmdHandler,
|
|||||||
OvsReadPacketCmdHandler,
|
OvsReadPacketCmdHandler,
|
||||||
OvsCtDeleteCmdHandler,
|
OvsCtDeleteCmdHandler,
|
||||||
OvsCtDumpCmdHandler,
|
OvsCtDumpCmdHandler,
|
||||||
OvsCtLimitHandler;
|
OvsCtLimitHandler,
|
||||||
|
OvsMeterFeatureProbe,
|
||||||
|
OvsNewMeterCmdHandler,
|
||||||
|
OvsMeterDestroy,
|
||||||
|
OvsMeterGet;
|
||||||
|
|
||||||
static NTSTATUS HandleGetDpTransaction(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
|
static NTSTATUS HandleGetDpTransaction(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
|
||||||
UINT32 *replyLen);
|
UINT32 *replyLen);
|
||||||
@ -307,6 +311,43 @@ NETLINK_FAMILY nlCtFamilyOps = {
|
|||||||
.opsCount = ARRAY_SIZE(nlCtFamilyCmdOps)
|
.opsCount = ARRAY_SIZE(nlCtFamilyCmdOps)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Netlink Meter family */
|
||||||
|
NETLINK_CMD nlMeterFamilyCmdOps[] = {
|
||||||
|
{ .cmd = OVS_METER_CMD_FEATURES,
|
||||||
|
.handler = OvsMeterFeatureProbe,
|
||||||
|
.supportedDevOp = OVS_TRANSACTION_DEV_OP |
|
||||||
|
OVS_WRITE_DEV_OP | OVS_READ_DEV_OP,
|
||||||
|
.validateDpIndex = FALSE
|
||||||
|
},
|
||||||
|
{ .cmd = OVS_METER_CMD_SET,
|
||||||
|
.handler = OvsNewMeterCmdHandler,
|
||||||
|
.supportedDevOp = OVS_TRANSACTION_DEV_OP |
|
||||||
|
OVS_WRITE_DEV_OP | OVS_READ_DEV_OP,
|
||||||
|
.validateDpIndex = FALSE
|
||||||
|
},
|
||||||
|
{ .cmd = OVS_METER_CMD_GET,
|
||||||
|
.handler = OvsMeterGet,
|
||||||
|
.supportedDevOp = OVS_TRANSACTION_DEV_OP |
|
||||||
|
OVS_WRITE_DEV_OP | OVS_READ_DEV_OP,
|
||||||
|
.validateDpIndex = FALSE
|
||||||
|
},
|
||||||
|
{ .cmd = OVS_METER_CMD_DEL,
|
||||||
|
.handler = OvsMeterDestroy,
|
||||||
|
.supportedDevOp = OVS_TRANSACTION_DEV_OP |
|
||||||
|
OVS_WRITE_DEV_OP | OVS_READ_DEV_OP,
|
||||||
|
.validateDpIndex = FALSE
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
NETLINK_FAMILY nlMeterFamilyOps = {
|
||||||
|
.name = OVS_METER_FAMILY,
|
||||||
|
.id = OVS_WIN_NL_METER_FAMILY_ID,
|
||||||
|
.version = OVS_METER_VERSION,
|
||||||
|
.maxAttr = __OVS_METER_ATTR_MAX,
|
||||||
|
.cmds = nlMeterFamilyCmdOps,
|
||||||
|
.opsCount = ARRAY_SIZE(nlMeterFamilyCmdOps)
|
||||||
|
};
|
||||||
|
|
||||||
/* Netlink netdev family. */
|
/* Netlink netdev family. */
|
||||||
NETLINK_CMD nlNetdevFamilyCmdOps[] = {
|
NETLINK_CMD nlNetdevFamilyCmdOps[] = {
|
||||||
{ .cmd = OVS_WIN_NETDEV_CMD_GET,
|
{ .cmd = OVS_WIN_NETDEV_CMD_GET,
|
||||||
@ -952,6 +993,9 @@ OvsDeviceControl(PDEVICE_OBJECT deviceObject,
|
|||||||
case NFNL_TYPE_CT_DEL:
|
case NFNL_TYPE_CT_DEL:
|
||||||
nlFamilyOps = &nlCtFamilyOps;
|
nlFamilyOps = &nlCtFamilyOps;
|
||||||
break;
|
break;
|
||||||
|
case OVS_WIN_NL_METER_FAMILY_ID:
|
||||||
|
nlFamilyOps = &nlMeterFamilyOps;
|
||||||
|
break;
|
||||||
case OVS_WIN_NL_CTRL_FAMILY_ID:
|
case OVS_WIN_NL_CTRL_FAMILY_ID:
|
||||||
nlFamilyOps = &nlControlFamilyOps;
|
nlFamilyOps = &nlControlFamilyOps;
|
||||||
break;
|
break;
|
||||||
|
540
datapath-windows/ovsext/Meter.c
Normal file
540
datapath-windows/ovsext/Meter.c
Normal file
@ -0,0 +1,540 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Meter.h"
|
||||||
|
#include "precomp.h"
|
||||||
|
#include "Switch.h"
|
||||||
|
#include "User.h"
|
||||||
|
#include "Datapath.h"
|
||||||
|
#include "Event.h"
|
||||||
|
#include "NetProto.h"
|
||||||
|
#include "Flow.h"
|
||||||
|
#include "PacketParser.h"
|
||||||
|
#include "Util.h"
|
||||||
|
|
||||||
|
static PNDIS_RW_LOCK_EX meterGlobalTableLock;
|
||||||
|
PLIST_ENTRY meterGlobalTable;
|
||||||
|
|
||||||
|
const NL_POLICY nlMeterPolicy[OVS_METER_ATTR_MAX + 1] = {
|
||||||
|
[OVS_METER_ATTR_ID] = { .type = NL_A_U32, },
|
||||||
|
[OVS_METER_ATTR_KBPS] = { .type = NL_A_FLAG, .optional = TRUE },
|
||||||
|
[OVS_METER_ATTR_STATS] = { .minLen = sizeof(struct ovs_flow_stats),
|
||||||
|
.maxLen = sizeof(struct ovs_flow_stats),
|
||||||
|
.optional = TRUE },
|
||||||
|
[OVS_METER_ATTR_BANDS] = { .type = NL_A_NESTED, .optional = TRUE },
|
||||||
|
[OVS_METER_ATTR_USED] = { .type = NL_A_U64, .optional = TRUE },
|
||||||
|
[OVS_METER_ATTR_CLEAR] = { .type = NL_A_FLAG, .optional = TRUE },
|
||||||
|
[OVS_METER_ATTR_MAX_METERS] = { .type = NL_A_U32, .optional = TRUE },
|
||||||
|
[OVS_METER_ATTR_MAX_BANDS] = { .type = NL_A_U32, .optional = TRUE },
|
||||||
|
};
|
||||||
|
|
||||||
|
const NL_POLICY bandPolicy[OVS_BAND_ATTR_MAX + 1] = {
|
||||||
|
[OVS_BAND_ATTR_TYPE] = { .type = NL_A_U32, .optional = FALSE },
|
||||||
|
[OVS_BAND_ATTR_RATE] = { .type = NL_A_U32, .optional = TRUE },
|
||||||
|
[OVS_BAND_ATTR_BURST] = { .type = NL_A_U32, .optional = TRUE },
|
||||||
|
[OVS_BAND_ATTR_STATS] = { .minLen = sizeof(struct ovs_flow_stats),
|
||||||
|
.maxLen = sizeof(struct ovs_flow_stats),
|
||||||
|
.optional = TRUE },
|
||||||
|
};
|
||||||
|
|
||||||
|
NTSTATUS
|
||||||
|
OvsInitMeter(POVS_SWITCH_CONTEXT context)
|
||||||
|
{
|
||||||
|
UINT32 maxEntry = METER_HASH_BUCKET_MAX;
|
||||||
|
|
||||||
|
meterGlobalTableLock = NdisAllocateRWLock(context->NdisFilterHandle);
|
||||||
|
if (meterGlobalTableLock == NULL) {
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
meterGlobalTable = OvsAllocateMemoryWithTag(sizeof(LIST_ENTRY) * maxEntry,
|
||||||
|
OVS_METER_TAG);
|
||||||
|
if (!meterGlobalTable) {
|
||||||
|
NdisFreeRWLock(meterGlobalTableLock);
|
||||||
|
return NDIS_STATUS_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (UINT32 index = 0; index < maxEntry; index++) {
|
||||||
|
InitializeListHead(&meterGlobalTable[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NDIS_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NDIS_STATUS
|
||||||
|
FillBandIntoMeter(PNL_ATTR meterAttrs[], DpMeter *meter, PNL_MSG_HDR nlMsgHdr)
|
||||||
|
{
|
||||||
|
PNL_ATTR a = NULL;
|
||||||
|
INT rem = 0;
|
||||||
|
UINT32 bandMaxDelta = 0;
|
||||||
|
UINT32 attrOffset = 0;
|
||||||
|
DpMeterBand *band = NULL;
|
||||||
|
PNL_ATTR bandAttrs[OVS_BAND_ATTR_MAX + 1];
|
||||||
|
UINT16 nBands = 0;
|
||||||
|
|
||||||
|
band = meter->bands;
|
||||||
|
NL_ATTR_FOR_EACH(a, rem, NlAttrData(meterAttrs[OVS_METER_ATTR_BANDS]),
|
||||||
|
NlAttrGetSize(meterAttrs[OVS_METER_ATTR_BANDS])) {
|
||||||
|
RtlZeroMemory(bandAttrs, sizeof(bandAttrs));
|
||||||
|
attrOffset = (UINT32)((PCHAR)NlAttrData(a) - (PCHAR)nlMsgHdr);
|
||||||
|
if (!NlAttrParse(nlMsgHdr,
|
||||||
|
attrOffset,
|
||||||
|
NlAttrGetSize(a),
|
||||||
|
bandPolicy, ARRAY_SIZE(bandPolicy),
|
||||||
|
bandAttrs, ARRAY_SIZE(bandAttrs))) {
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bandAttrs[OVS_BAND_ATTR_TYPE]) {
|
||||||
|
band->type = NlAttrGetU32(bandAttrs[OVS_BAND_ATTR_TYPE]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bandAttrs[OVS_BAND_ATTR_RATE]) {
|
||||||
|
band->rate = NlAttrGetU32(bandAttrs[OVS_BAND_ATTR_RATE]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bandAttrs[OVS_BAND_ATTR_BURST]) {
|
||||||
|
band->burst_size = NlAttrGetU32(bandAttrs[OVS_BAND_ATTR_BURST]);
|
||||||
|
}
|
||||||
|
|
||||||
|
band->bucket = (band->burst_size + band->rate) * 1000;
|
||||||
|
bandMaxDelta = (UINT32)((band->bucket / band->rate) / 10);
|
||||||
|
if (bandMaxDelta > meter->maxDelta) {
|
||||||
|
meter->maxDelta = bandMaxDelta;
|
||||||
|
}
|
||||||
|
|
||||||
|
nBands++;
|
||||||
|
band++;
|
||||||
|
}
|
||||||
|
|
||||||
|
meter->nBands = nBands;
|
||||||
|
return NDIS_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NDIS_STATUS
|
||||||
|
OvsNewMeterCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
|
||||||
|
UINT32 *replyLen)
|
||||||
|
{
|
||||||
|
DpMeter *meter = NULL;
|
||||||
|
POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;
|
||||||
|
PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
|
||||||
|
PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
|
||||||
|
POVS_HDR ovsHdr = &(msgIn->ovsHdr);
|
||||||
|
LOCK_STATE_EX lockState;
|
||||||
|
PNL_ATTR meterAttrs[ARRAY_SIZE(nlMeterPolicy)];
|
||||||
|
ASSERT(usrParamsCtx->inputBuffer != NULL);
|
||||||
|
PNL_MSG_HDR nlMsgOutHdr = NULL;
|
||||||
|
NL_BUFFER nlBuf;
|
||||||
|
NL_ERROR nlError = NL_ERROR_SUCCESS;
|
||||||
|
|
||||||
|
if (!NlAttrParse((PNL_MSG_HDR)msgIn,
|
||||||
|
NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN,
|
||||||
|
NlMsgAttrsLen((PNL_MSG_HDR)msgIn),
|
||||||
|
nlMeterPolicy, ARRAY_SIZE(nlMeterPolicy),
|
||||||
|
meterAttrs, ARRAY_SIZE(meterAttrs))) {
|
||||||
|
nlError = NL_ERROR_NOMSG;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
meter = OvsAllocateMemoryWithTag(sizeof(*meter), OVS_METER_TAG);
|
||||||
|
if (!meter) {
|
||||||
|
nlError = NL_ERROR_NOMEM;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlZeroMemory(meter, sizeof(*meter));
|
||||||
|
meter->id = NlAttrGetU32(meterAttrs[OVS_METER_ATTR_ID]);
|
||||||
|
meter->kbps = meterAttrs[OVS_METER_ATTR_KBPS] ? 1 : 0;
|
||||||
|
meter->keepStatus = meterAttrs[OVS_METER_ATTR_CLEAR] ? 1 : 0;
|
||||||
|
if (meter->keepStatus && meterAttrs[OVS_METER_ATTR_STATS]) {
|
||||||
|
meter->stats = *(struct ovs_flow_stats *)NlAttrData(
|
||||||
|
meterAttrs[OVS_METER_ATTR_STATS]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FillBandIntoMeter(meterAttrs, meter, nlMsgHdr) != NDIS_STATUS_SUCCESS) {
|
||||||
|
nlError = NL_ERROR_NOMSG;
|
||||||
|
OvsFreeMemoryWithTag(meter, OVS_METER_TAG);
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
NdisAcquireRWLockWrite(meterGlobalTableLock, &lockState, 0);
|
||||||
|
InsertHeadList(&meterGlobalTable[meter->id & (METER_HASH_BUCKET_MAX - 1)],
|
||||||
|
&(meter->link));
|
||||||
|
NdisReleaseRWLock(meterGlobalTableLock, &lockState);
|
||||||
|
|
||||||
|
NlBufInit(&nlBuf, usrParamsCtx->outputBuffer, usrParamsCtx->outputLength);
|
||||||
|
nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, 0, 0));
|
||||||
|
if (!NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,
|
||||||
|
nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
|
||||||
|
genlMsgHdr->cmd, OVS_METER_CMD_GET,
|
||||||
|
ovsHdr->dp_ifindex)) {
|
||||||
|
nlError = NL_ERROR_NOMSG;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!buildOvsMeterReplyMsg(&nlBuf, meter)) {
|
||||||
|
nlError = NL_ERROR_NOMEM;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
NlMsgSetSize(nlMsgOutHdr, NlBufSize(&nlBuf));
|
||||||
|
NlMsgAlignSize(nlMsgOutHdr);
|
||||||
|
*replyLen += NlMsgSize(nlMsgOutHdr);
|
||||||
|
|
||||||
|
Done:
|
||||||
|
if (nlError != NL_ERROR_SUCCESS) {
|
||||||
|
POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
|
||||||
|
usrParamsCtx->outputBuffer;
|
||||||
|
|
||||||
|
ASSERT(msgError);
|
||||||
|
NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);
|
||||||
|
ASSERT(*replyLen != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NDIS_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NDIS_STATUS OvsMeterFeatureProbe(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
|
||||||
|
UINT32 *replyLen)
|
||||||
|
{
|
||||||
|
POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;
|
||||||
|
PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
|
||||||
|
POVS_HDR ovsHdr = &(msgIn->ovsHdr);
|
||||||
|
PNL_MSG_HDR nlMsgOutHdr = NULL;
|
||||||
|
BOOLEAN ok = FALSE;
|
||||||
|
PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
|
||||||
|
NL_BUFFER nlBuf;
|
||||||
|
NL_ERROR nlError = NL_ERROR_SUCCESS;
|
||||||
|
UINT32 bandsOffset = 0;
|
||||||
|
UINT32 bandAttrOffset = 0;
|
||||||
|
|
||||||
|
NlBufInit(&nlBuf, usrParamsCtx->outputBuffer, usrParamsCtx->outputLength);
|
||||||
|
nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, 0, 0));
|
||||||
|
ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,
|
||||||
|
nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
|
||||||
|
genlMsgHdr->cmd, OVS_METER_CMD_FEATURES,
|
||||||
|
ovsHdr->dp_ifindex);
|
||||||
|
if (!ok) {
|
||||||
|
nlError = NL_ERROR_NOMSG;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!NlMsgPutTailU32(&nlBuf, OVS_METER_ATTR_MAX_METERS, UINT32_MAX)) {
|
||||||
|
nlError = NL_ERROR_NOMSG;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!NlMsgPutTailU32(&nlBuf, OVS_METER_ATTR_MAX_BANDS, OVS_MAX_BANDS)) {
|
||||||
|
nlError = NL_ERROR_NOMSG;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
bandsOffset = NlMsgStartNested(&nlBuf, OVS_METER_ATTR_BANDS);
|
||||||
|
bandAttrOffset = NlMsgStartNested(&nlBuf, OVS_METER_ATTR_UNSPEC);
|
||||||
|
if (!NlMsgPutTailU32(&nlBuf, OVS_BAND_ATTR_TYPE,
|
||||||
|
OVS_METER_BAND_TYPE_DROP)) {
|
||||||
|
nlError = NL_ERROR_NOMSG;
|
||||||
|
goto Done;
|
||||||
|
|
||||||
|
}
|
||||||
|
NlMsgEndNested(&nlBuf, bandAttrOffset);
|
||||||
|
NlMsgEndNested(&nlBuf, bandsOffset);
|
||||||
|
|
||||||
|
NlMsgSetSize(nlMsgOutHdr, NlBufSize(&nlBuf));
|
||||||
|
NlMsgAlignSize(nlMsgOutHdr);
|
||||||
|
*replyLen += NlMsgSize(nlMsgOutHdr);
|
||||||
|
|
||||||
|
Done:
|
||||||
|
if (nlError != NL_ERROR_SUCCESS) {
|
||||||
|
POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
|
||||||
|
usrParamsCtx->outputBuffer;
|
||||||
|
|
||||||
|
ASSERT(msgError);
|
||||||
|
NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);
|
||||||
|
ASSERT(*replyLen != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
buildOvsMeterReplyMsg(NL_BUFFER *nlBuf, DpMeter *dpMeter)
|
||||||
|
{
|
||||||
|
BOOLEAN ok = FALSE;
|
||||||
|
UINT32 bandAttrOffset;
|
||||||
|
UINT32 bandsOffset;
|
||||||
|
|
||||||
|
/* Add meter element. */
|
||||||
|
ok = NlMsgPutTailU32(nlBuf, OVS_METER_ATTR_ID, dpMeter->id);
|
||||||
|
if (!ok) {
|
||||||
|
OVS_LOG_ERROR("Could not add meter id %d.", dpMeter->id);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
ok = NlMsgPutTailUnspec(nlBuf, OVS_METER_ATTR_STATS,
|
||||||
|
(PCHAR)&(dpMeter->stats),
|
||||||
|
sizeof(dpMeter->stats));
|
||||||
|
if (!ok) {
|
||||||
|
OVS_LOG_ERROR("Could not add ovs meter stats.");
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
bandsOffset = NlMsgStartNested(nlBuf, OVS_METER_ATTR_BANDS);
|
||||||
|
for (int index = 0; index < dpMeter->nBands; index++) {
|
||||||
|
bandAttrOffset = NlMsgStartNested(nlBuf, OVS_BAND_ATTR_UNSPEC);
|
||||||
|
ok = NlMsgPutTailUnspec(nlBuf, OVS_BAND_ATTR_STATS,
|
||||||
|
(PCHAR)&(dpMeter->bands[index].stats),
|
||||||
|
sizeof(dpMeter->bands[index].stats));
|
||||||
|
NlMsgEndNested(nlBuf, bandAttrOffset);
|
||||||
|
if (!ok) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NlMsgEndNested(nlBuf, bandsOffset);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
NDIS_STATUS
|
||||||
|
OvsMeterGet(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
|
||||||
|
UINT32 *replyLen)
|
||||||
|
{
|
||||||
|
POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;
|
||||||
|
PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
|
||||||
|
POVS_HDR ovsHdr = &(msgIn->ovsHdr);
|
||||||
|
PNL_MSG_HDR nlMsgOutHdr = NULL;
|
||||||
|
PNL_ATTR meterAttrs[ARRAY_SIZE(nlMeterPolicy)];
|
||||||
|
UINT32 meterId = 0;
|
||||||
|
DpMeter *dpMeter = NULL;
|
||||||
|
BOOLEAN ok = FALSE;
|
||||||
|
PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
|
||||||
|
NL_BUFFER nlBuf;
|
||||||
|
NL_ERROR nlError = NL_ERROR_SUCCESS;
|
||||||
|
LOCK_STATE_EX lockState;
|
||||||
|
|
||||||
|
if (!NlAttrParse((PNL_MSG_HDR)msgIn,
|
||||||
|
NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN,
|
||||||
|
NlMsgAttrsLen((PNL_MSG_HDR)msgIn),
|
||||||
|
nlMeterPolicy, ARRAY_SIZE(nlMeterPolicy),
|
||||||
|
meterAttrs, ARRAY_SIZE(meterAttrs))) {
|
||||||
|
nlError = NL_ERROR_NOMSG;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
NlBufInit(&nlBuf, usrParamsCtx->outputBuffer, usrParamsCtx->outputLength);
|
||||||
|
meterId = NlAttrGetU32(meterAttrs[OVS_METER_ATTR_ID]);
|
||||||
|
|
||||||
|
/* Reply message header */
|
||||||
|
nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, 0, 0));
|
||||||
|
ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,
|
||||||
|
nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
|
||||||
|
genlMsgHdr->cmd, OVS_METER_CMD_GET,
|
||||||
|
ovsHdr->dp_ifindex);
|
||||||
|
if (!ok) {
|
||||||
|
nlError = NL_ERROR_NOMSG;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
NdisAcquireRWLockRead(meterGlobalTableLock, &lockState, 0);
|
||||||
|
dpMeter = OvsMeterLookup(meterId);
|
||||||
|
if (!dpMeter) {
|
||||||
|
OVS_LOG_WARN("Has not find %d associated meter", meterId);
|
||||||
|
nlError = NL_ERROR_EXIST;
|
||||||
|
NdisReleaseRWLock(meterGlobalTableLock, &lockState);
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!buildOvsMeterReplyMsg(&nlBuf, dpMeter)) {
|
||||||
|
nlError = NL_ERROR_NOMEM;
|
||||||
|
OVS_LOG_ERROR("Could not build ovs meter reply msg.");
|
||||||
|
NdisReleaseRWLock(meterGlobalTableLock, &lockState);
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
NdisReleaseRWLock(meterGlobalTableLock, &lockState);
|
||||||
|
NlMsgSetSize(nlMsgOutHdr, NlBufSize(&nlBuf));
|
||||||
|
NlMsgAlignSize(nlMsgOutHdr);
|
||||||
|
*replyLen += NlMsgSize(nlMsgOutHdr);
|
||||||
|
|
||||||
|
Done:
|
||||||
|
if (nlError != NL_ERROR_SUCCESS) {
|
||||||
|
POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
|
||||||
|
usrParamsCtx->outputBuffer;
|
||||||
|
|
||||||
|
ASSERT(msgError);
|
||||||
|
NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);
|
||||||
|
ASSERT(*replyLen != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NDIS_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
NDIS_STATUS
|
||||||
|
OvsMeterDestroy(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
|
||||||
|
UINT32 *replyLen)
|
||||||
|
{
|
||||||
|
POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;
|
||||||
|
PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg);
|
||||||
|
POVS_HDR ovsHdr = &(msgIn->ovsHdr);
|
||||||
|
PNL_MSG_HDR nlMsgOutHdr = NULL;
|
||||||
|
PNL_ATTR meterAttrs[ARRAY_SIZE(nlMeterPolicy)];
|
||||||
|
PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg);
|
||||||
|
LOCK_STATE_EX lockState;
|
||||||
|
UINT32 meterId = 0;
|
||||||
|
BOOLEAN ok;
|
||||||
|
NL_BUFFER nlBuf;
|
||||||
|
NL_ERROR nlError = NL_ERROR_SUCCESS;
|
||||||
|
|
||||||
|
if (!NlAttrParse((PNL_MSG_HDR)msgIn,
|
||||||
|
NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN,
|
||||||
|
NlMsgAttrsLen((PNL_MSG_HDR)msgIn),
|
||||||
|
nlMeterPolicy, ARRAY_SIZE(nlMeterPolicy),
|
||||||
|
meterAttrs, ARRAY_SIZE(meterAttrs))) {
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
NlBufInit(&nlBuf, usrParamsCtx->outputBuffer, usrParamsCtx->outputLength);
|
||||||
|
|
||||||
|
meterId = NlAttrGetU32(meterAttrs[OVS_METER_ATTR_ID]);
|
||||||
|
nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, 0, 0));
|
||||||
|
ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0,
|
||||||
|
nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid,
|
||||||
|
genlMsgHdr->cmd, OVS_METER_CMD_DEL,
|
||||||
|
ovsHdr->dp_ifindex);
|
||||||
|
if (!ok) {
|
||||||
|
nlError = NL_ERROR_NOMEM;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
NdisAcquireRWLockWrite(meterGlobalTableLock, &lockState, 0);
|
||||||
|
PLIST_ENTRY head = &meterGlobalTable[meterId & (METER_HASH_BUCKET_MAX - 1)];
|
||||||
|
PLIST_ENTRY link, next;
|
||||||
|
DpMeter *entry = NULL;
|
||||||
|
|
||||||
|
LIST_FORALL_SAFE(head, link, next) {
|
||||||
|
entry = CONTAINING_RECORD(link, DpMeter, link);
|
||||||
|
if (entry->id == meterId) {
|
||||||
|
if (!buildOvsMeterReplyMsg(&nlBuf, entry)) {
|
||||||
|
nlError = NL_ERROR_NOMEM;
|
||||||
|
NdisReleaseRWLock(meterGlobalTableLock, &lockState);
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
RemoveEntryList(&entry->link);
|
||||||
|
OvsFreeMemoryWithTag(entry, OVS_METER_TAG);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NdisReleaseRWLock(meterGlobalTableLock, &lockState);
|
||||||
|
NlMsgSetSize(nlMsgOutHdr, NlBufSize(&nlBuf));
|
||||||
|
NlMsgAlignSize(nlMsgOutHdr);
|
||||||
|
*replyLen += NlMsgSize(nlMsgOutHdr);
|
||||||
|
|
||||||
|
Done:
|
||||||
|
if (nlError != NL_ERROR_SUCCESS) {
|
||||||
|
POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
|
||||||
|
usrParamsCtx->outputBuffer;
|
||||||
|
|
||||||
|
ASSERT(msgError);
|
||||||
|
NlBuildErrorMsg(msgIn, msgError, nlError, replyLen);
|
||||||
|
ASSERT(*replyLen != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NDIS_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
DpMeter*
|
||||||
|
OvsMeterLookup(UINT32 meterId)
|
||||||
|
{
|
||||||
|
PLIST_ENTRY head = &meterGlobalTable[meterId & (METER_HASH_BUCKET_MAX - 1)];
|
||||||
|
PLIST_ENTRY link, next;
|
||||||
|
DpMeter *entry = NULL;
|
||||||
|
|
||||||
|
LIST_FORALL_SAFE(head, link, next) {
|
||||||
|
entry = CONTAINING_RECORD(link, DpMeter, link);
|
||||||
|
if (entry->id == meterId) {
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
OvsMeterExecute(OvsForwardingContext *fwdCtx, UINT32 meterId)
|
||||||
|
{
|
||||||
|
DpMeter *dpMeter;
|
||||||
|
DpMeterBand *band;
|
||||||
|
UINT32 longDeltaMs;
|
||||||
|
UINT32 deltaMs;
|
||||||
|
UINT64 currentTime;
|
||||||
|
LOCK_STATE_EX lockState;
|
||||||
|
UINT32 cost;
|
||||||
|
UINT32 bandExceededRate = 0;
|
||||||
|
INT32 bandExceedIndex = -1;
|
||||||
|
UINT64 maxBucketSize = 0;
|
||||||
|
|
||||||
|
NdisAcquireRWLockRead(meterGlobalTableLock, &lockState, 0);
|
||||||
|
dpMeter = OvsMeterLookup(meterId);
|
||||||
|
if (!dpMeter) {
|
||||||
|
OVS_LOG_ERROR("Not found meter id %d associated meter.", meterId);
|
||||||
|
NdisReleaseRWLock(meterGlobalTableLock, &lockState);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
NdisGetCurrentSystemTime((LARGE_INTEGER *)¤tTime);
|
||||||
|
/* currentTime represent count of 100-nanosecond intervals, to convert it to
|
||||||
|
* ms, we need to divide 10000. */
|
||||||
|
longDeltaMs = (UINT32)((currentTime - dpMeter->used) / 10000);
|
||||||
|
deltaMs = longDeltaMs > dpMeter->maxDelta ? dpMeter->maxDelta :
|
||||||
|
longDeltaMs;
|
||||||
|
dpMeter->used = currentTime;
|
||||||
|
dpMeter->stats.n_packets += 1;
|
||||||
|
dpMeter->stats.n_bytes += OvsPacketLenNBL(fwdCtx->curNbl);
|
||||||
|
cost = dpMeter->kbps ? OvsPacketLenNBL(fwdCtx->curNbl) * 8 : 1000;
|
||||||
|
for (int index = 0; index < dpMeter->nBands; index++) {
|
||||||
|
band = &(dpMeter->bands[index]);
|
||||||
|
maxBucketSize = (band->burst_size + band->rate) * 1000LL;
|
||||||
|
band->bucket += deltaMs * band->rate;
|
||||||
|
if (band->bucket > maxBucketSize) {
|
||||||
|
band->bucket = maxBucketSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (band->bucket >= cost) {
|
||||||
|
band->bucket -= cost;
|
||||||
|
band->stats.n_packets += 1;
|
||||||
|
band->stats.n_bytes += OvsPacketLenNBL(fwdCtx->curNbl);
|
||||||
|
} else if (band->rate > bandExceededRate) {
|
||||||
|
bandExceededRate = band->rate;
|
||||||
|
bandExceedIndex = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bandExceedIndex >= 0) {
|
||||||
|
band = &(dpMeter->bands[bandExceedIndex]);
|
||||||
|
band->stats.n_packets += 1;
|
||||||
|
band->stats.n_bytes += OvsPacketLenNBL(fwdCtx->curNbl);
|
||||||
|
if (band->type == OVS_METER_BAND_TYPE_DROP) {
|
||||||
|
NdisReleaseRWLock(meterGlobalTableLock, &lockState);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NdisReleaseRWLock(meterGlobalTableLock, &lockState);
|
||||||
|
return FALSE;
|
||||||
|
}
|
68
datapath-windows/ovsext/Meter.h
Normal file
68
datapath-windows/ovsext/Meter.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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 OVS_METER_H
|
||||||
|
#define OVS_METER_H
|
||||||
|
|
||||||
|
#include "precomp.h"
|
||||||
|
#include "Switch.h"
|
||||||
|
#include "User.h"
|
||||||
|
#include "Datapath.h"
|
||||||
|
#include "Event.h"
|
||||||
|
#include "NetProto.h"
|
||||||
|
#include "Netlink/Netlink.h"
|
||||||
|
#include "Flow.h"
|
||||||
|
|
||||||
|
#define OVS_MAX_BANDS 1
|
||||||
|
#define OVS_MAX_METERS 32
|
||||||
|
#define METER_HASH_BUCKET_MAX 1024
|
||||||
|
|
||||||
|
typedef struct _DpMeterBand {
|
||||||
|
UINT32 type;
|
||||||
|
UINT32 rate;
|
||||||
|
UINT32 burst_size;
|
||||||
|
UINT64 bucket;
|
||||||
|
struct ovs_flow_stats stats;
|
||||||
|
} DpMeterBand;
|
||||||
|
|
||||||
|
typedef struct _DpMeter {
|
||||||
|
LIST_ENTRY link;
|
||||||
|
UINT32 id;
|
||||||
|
UINT16 kbps:1;
|
||||||
|
UINT16 keepStatus:1;
|
||||||
|
UINT16 nBands;
|
||||||
|
UINT32 maxDelta;
|
||||||
|
UINT64 used;
|
||||||
|
struct ovs_flow_stats stats;
|
||||||
|
DpMeterBand bands[OVS_MAX_BANDS];
|
||||||
|
} DpMeter;
|
||||||
|
|
||||||
|
NTSTATUS OvsInitMeter(POVS_SWITCH_CONTEXT context);
|
||||||
|
NDIS_STATUS OvsNewMeterCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
|
||||||
|
UINT32 *replyLen);
|
||||||
|
NDIS_STATUS OvsMeterFeatureProbe(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
|
||||||
|
UINT32 *replyLen);
|
||||||
|
|
||||||
|
NDIS_STATUS OvsMeterDestroy(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
|
||||||
|
UINT32 *replyLen);
|
||||||
|
DpMeter* OvsMeterLookup(UINT32 meterId);
|
||||||
|
BOOLEAN
|
||||||
|
OvsMeterExecute(OvsForwardingContext *fwdCtx, UINT32 meterId);
|
||||||
|
BOOLEAN
|
||||||
|
buildOvsMeterReplyMsg(NL_BUFFER *nlBuf, DpMeter *dpMeter);
|
||||||
|
|
||||||
|
|
||||||
|
#endif //OVS_METER_H
|
@ -24,6 +24,7 @@
|
|||||||
#include "Switch.h"
|
#include "Switch.h"
|
||||||
#include "Vport.h"
|
#include "Vport.h"
|
||||||
#include "Event.h"
|
#include "Event.h"
|
||||||
|
#include "Meter.h"
|
||||||
#include "Flow.h"
|
#include "Flow.h"
|
||||||
#include "IpHelper.h"
|
#include "IpHelper.h"
|
||||||
#include "Oid.h"
|
#include "Oid.h"
|
||||||
@ -247,6 +248,13 @@ OvsCreateSwitch(NDIS_HANDLE ndisFilterHandle,
|
|||||||
goto create_switch_done;
|
goto create_switch_done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status = OvsInitMeter(switchContext);
|
||||||
|
if (status != STATUS_SUCCESS) {
|
||||||
|
OvsUninitSwitchContext(switchContext);
|
||||||
|
OVS_LOG_ERROR("Exit: Failed to initialize Ovs meter.");
|
||||||
|
goto create_switch_done;
|
||||||
|
}
|
||||||
|
|
||||||
*switchContextOut = switchContext;
|
*switchContextOut = switchContext;
|
||||||
|
|
||||||
create_switch_done:
|
create_switch_done:
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
#define OVS_TUNFLT_POOL_TAG 'WSVO'
|
#define OVS_TUNFLT_POOL_TAG 'WSVO'
|
||||||
#define OVS_RECIRC_POOL_TAG 'CSVO'
|
#define OVS_RECIRC_POOL_TAG 'CSVO'
|
||||||
#define OVS_CT_POOL_TAG 'CTVO'
|
#define OVS_CT_POOL_TAG 'CTVO'
|
||||||
|
#define OVS_METER_TAG 'MEVO'
|
||||||
#define OVS_GENEVE_POOL_TAG 'GNVO'
|
#define OVS_GENEVE_POOL_TAG 'GNVO'
|
||||||
#define OVS_IPFRAG_POOL_TAG 'FGVO'
|
#define OVS_IPFRAG_POOL_TAG 'FGVO'
|
||||||
#define OVS_IP6FRAG_POOL_TAG 'F6VO'
|
#define OVS_IP6FRAG_POOL_TAG 'F6VO'
|
||||||
|
@ -165,6 +165,7 @@
|
|||||||
<ClInclude Include="Ip6Fragment.h" />
|
<ClInclude Include="Ip6Fragment.h" />
|
||||||
<ClInclude Include="IpHelper.h" />
|
<ClInclude Include="IpHelper.h" />
|
||||||
<ClInclude Include="Jhash.h" />
|
<ClInclude Include="Jhash.h" />
|
||||||
|
<ClInclude Include="Meter.h" />
|
||||||
<ClInclude Include="Mpls.h" />
|
<ClInclude Include="Mpls.h" />
|
||||||
<ClInclude Include="Netlink/Netlink.h" />
|
<ClInclude Include="Netlink/Netlink.h" />
|
||||||
<ClInclude Include="Netlink/NetlinkBuf.h" />
|
<ClInclude Include="Netlink/NetlinkBuf.h" />
|
||||||
@ -410,6 +411,7 @@
|
|||||||
<ClCompile Include="Ip6Fragment.c" />
|
<ClCompile Include="Ip6Fragment.c" />
|
||||||
<ClCompile Include="IpHelper.c" />
|
<ClCompile Include="IpHelper.c" />
|
||||||
<ClCompile Include="Jhash.c" />
|
<ClCompile Include="Jhash.c" />
|
||||||
|
<ClCompile Include="Meter.c" />
|
||||||
<ClCompile Include="Netlink/Netlink.c" />
|
<ClCompile Include="Netlink/Netlink.c" />
|
||||||
<ClCompile Include="Netlink/NetlinkBuf.c" />
|
<ClCompile Include="Netlink/NetlinkBuf.c" />
|
||||||
<ClCompile Include="Datapath.c" />
|
<ClCompile Include="Datapath.c" />
|
||||||
|
@ -1574,6 +1574,11 @@ do_lookup_genl_family(const char *name, struct nlattr **attrs,
|
|||||||
family_name = OVS_FLOW_FAMILY;
|
family_name = OVS_FLOW_FAMILY;
|
||||||
family_version = OVS_FLOW_VERSION;
|
family_version = OVS_FLOW_VERSION;
|
||||||
family_attrmax = OVS_FLOW_ATTR_MAX;
|
family_attrmax = OVS_FLOW_ATTR_MAX;
|
||||||
|
} else if (!strcmp(name, OVS_METER_FAMILY)) {
|
||||||
|
family_id = OVS_WIN_NL_METER_FAMILY_ID;
|
||||||
|
family_name = OVS_METER_FAMILY;
|
||||||
|
family_version = OVS_METER_VERSION;
|
||||||
|
family_attrmax = __OVS_METER_ATTR_MAX;
|
||||||
} else if (!strcmp(name, OVS_WIN_NETDEV_FAMILY)) {
|
} else if (!strcmp(name, OVS_WIN_NETDEV_FAMILY)) {
|
||||||
family_id = OVS_WIN_NL_NETDEV_FAMILY_ID;
|
family_id = OVS_WIN_NL_NETDEV_FAMILY_ID;
|
||||||
family_name = OVS_WIN_NETDEV_FAMILY;
|
family_name = OVS_WIN_NETDEV_FAMILY;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user