hi Ankur, Thanks for working on this. LG but for minor comments I had. Acked-by: Nithin Raju <nit...@vmware.com>
On Sep 29, 2014, at 3:34 PM, Ankur Sharma <ankursha...@vmware.com> wrote: > In this patch we have implemented the flow dump. > > Signed-off-by: Ankur Sharma <ankursha...@vmware.com> > --- > datapath-windows/ovsext/Flow.c | 635 ++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 625 insertions(+), 10 deletions(-) > > diff --git a/datapath-windows/ovsext/Flow.c b/datapath-windows/ovsext/Flow.c > index d1c318c..e818e23 100644 > --- a/datapath-windows/ovsext/Flow.c > +++ b/datapath-windows/ovsext/Flow.c > @@ -20,6 +20,7 @@ > #include "Jhash.h" > #include "Flow.h" > #include "PacketParser.h" > +#include "Datapath.h" > > #ifdef OVS_DBG_MOD > #undef OVS_DBG_MOD > @@ -35,7 +36,7 @@ extern POVS_SWITCH_CONTEXT gOvsSwitchContext; > extern UINT64 ovsTimeIncrementPerTick; > > static NTSTATUS ReportFlowInfo(OvsFlow *flow, UINT32 getFlags, > - UINT32 getActionsLen, OvsFlowInfo *info); > + OvsFlowInfo *info); > static NTSTATUS HandleFlowPut(OvsFlowPut *put, > OVS_DATAPATH *datapath, > struct OvsFlowStats *stats); > @@ -61,6 +62,35 @@ static VOID _MapNlToFlowPutFlags(PGENL_MSG_HDR genlMsgHdr, > PNL_ATTR flowAttrClear, > OvsFlowPut *mappedFlow); > > +static NTSTATUS _FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, > + UINT32 *replyLen); > +static NTSTATUS _FlowNlDumpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, > + 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, > + uint32_t actionsLen, > + PNL_ATTR actions); > + > +static NTSTATUS _MapFlowIpv4KeyToNlKey(PNL_BUFFER nlBuf, > + IpKey *ipv4FlowPutKey); > +static NTSTATUS _MapFlowIpv6KeyToNlKey(PNL_BUFFER nlBuf, > + Ipv6Key *ipv6FlowPutKey, > + Icmp6Key *ipv6FlowPutIcmpKey); > +static NTSTATUS _MapFlowArpKeyToNlKey(PNL_BUFFER nlBuf, > + ArpKey *arpFlowPutKey); > + > +static NTSTATUS OvsDoDumpFlows(OvsFlowDumpInput *dumpInput, > + OvsFlowDumpOutput *dumpOutput, > + UINT32 *replyLen); > + > + > #define OVS_FLOW_TABLE_SIZE 2048 > #define OVS_FLOW_TABLE_MASK (OVS_FLOW_TABLE_SIZE -1) > #define HASH_BUCKET(hash) ((hash) & OVS_FLOW_TABLE_MASK) > @@ -297,8 +327,10 @@ OvsFlowNlCmdHandler(POVS_USER_PARAMS_CONTEXT > usrParamsCtx, > (PCHAR)(&replyStats), sizeof(replyStats))) { > OVS_LOG_ERROR("Adding OVS_FLOW_ATTR_STATS attribute failed."); > rc = STATUS_UNSUCCESSFUL; > + goto done; > } > > + msgOut->nlMsg.nlmsgLen = NLMSG_ALIGN(NlBufSize(&nlBuf)); > *replyLen = msgOut->nlMsg.nlmsgLen; > > done: > @@ -318,9 +350,597 @@ OvsFlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT > usrParamsCtx, > NTSTATUS rc = STATUS_SUCCESS; > *replyLen = 0; Setting *replyLen = 0 is not necessary. It has been initialized to 0 in OvsDeviceControl(). > + if (usrParamsCtx->devOp == OVS_TRANSACTION_DEV_OP) { > + rc = _FlowNlGetCmdHandler(usrParamsCtx, replyLen); > + } else { > + rc = _FlowNlDumpCmdHandler(usrParamsCtx, replyLen); > + } > + > + return rc; > +} > + > +NTSTATUS > +_FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, > + UINT32 *replyLen) > +{ > + NTSTATUS rc = STATUS_SUCCESS; > + > UNREFERENCED_PARAMETER(usrParamsCtx); > - UNREFERENCED_PARAMETER(replyLen); > > + *replyLen = 0; *replyLen = 0 is not necessary. > + > + return rc; > +} > + > +NTSTATUS > +_FlowNlDumpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, > + UINT32 *replyLen) > +{ > + NTSTATUS rc = STATUS_SUCCESS; > + UINT32 temp = 0; /* To keep compiler happy for calling OvsDoDumpFlows > */ > + > + POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE) > + (usrParamsCtx->ovsInstance); > + > + if (usrParamsCtx->devOp == OVS_WRITE_DEV_OP) { > + /* Dump Start */ > + OvsSetupDumpStart(usrParamsCtx); > + goto done; > + } > + > + POVS_MESSAGE msgIn = instance->dumpState.ovsMsg; > + PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg); > + PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg); > + POVS_HDR ovsHdr = &(msgIn->ovsHdr); > + PNL_MSG_HDR nlMsgOutHdr = NULL; > + UINT32 hdrOffset = 0; > + > + /* Get Next */ > + OvsFlowDumpOutput dumpOutput; > + OvsFlowDumpInput dumpInput; > + NL_BUFFER nlBuf; > + > + NlBufInit(&nlBuf, usrParamsCtx->outputBuffer, > + usrParamsCtx->outputLength); > + > + ASSERT(usrParamsCtx->devOp == OVS_READ_DEV_OP); > + ASSERT(usrParamsCtx->outputLength); > + > + RtlZeroMemory(&dumpInput, sizeof(OvsFlowDumpInput)); > + RtlZeroMemory(&dumpOutput, sizeof(OvsFlowDumpOutput)); > + > + dumpInput.dpNo = ovsHdr->dp_ifindex; > + dumpInput.getFlags = FLOW_GET_KEY | FLOW_GET_STATS | FLOW_GET_ACTIONS; > + > + /* Lets provide as many flows to userspace as possible. */ > + do { > + dumpInput.position[0] = instance->dumpState.index[0]; > + dumpInput.position[1] = instance->dumpState.index[1]; > + > + rc = OvsDoDumpFlows(&dumpInput, &dumpOutput, &temp); > + if (rc != STATUS_SUCCESS) { > + OVS_LOG_ERROR("OvsDoDumpFlows failed with rc: %d", rc); > + break; > + } > + > + /* Done with Dump, send NLMSG_DONE */ > + if (!(dumpOutput.n)) { > + OVS_LOG_INFO("Dump Done"); > + > + nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, NlBufSize(&nlBuf), > 0)); > + rc = NlFillNlHdr(&nlBuf, NLMSG_DONE, NLM_F_MULTI, > + nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid); > + > + if (rc != STATUS_SUCCESS) { > + OVS_LOG_ERROR("Unable to prepare DUMP_DONE reply."); > + break; > + } > + > + NlMsgAlignSize(nlMsgOutHdr); > + *replyLen += NlMsgSize(nlMsgOutHdr); > + > + FreeUserDumpState(instance); > + break; > + } else { > + > + hdrOffset = NlBufSize(&nlBuf); > + nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, hdrOffset, 0)); > + > + /* Netlink header */ > + rc = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, NLM_F_MULTI, > + nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid, > + genlMsgHdr->cmd, genlMsgHdr->version, > + ovsHdr->dp_ifindex); > + > + if (rc != STATUS_SUCCESS) > + break; rc != STATUS_SUCCESS is not a failure case here. We should be resetting rc to STATUS_SUCCESS, and exiting the function. Also you need to add '{}' paranthesis to the if. > + > + /* Time to add attributes */ > + rc = _MapFlowInfoToNl(&nlBuf, &(dumpOutput.flow)); > + if (rc != STATUS_SUCCESS) { > + /* Adding the attribute failed, we are out of > + space in the buffer, remove the appended OVS header*/ > + NlMsgSetSize(nlMsgOutHdr, > + NlMsgSize(nlMsgOutHdr) - > + sizeof(struct _OVS_MESSAGE)); > + OVS_LOG_ERROR("_MapFlowInfoToNl failed."); Is this a failure case if we run out of buffer space? I think we should reset rc to STATUS_SUCCESS, if we can ensure that there's at least one flow added. > + break; > + } > + > + NlMsgSetSize(nlMsgOutHdr, NlBufSize(&nlBuf) - hdrOffset); > + NlMsgAlignSize(nlMsgOutHdr); > + *replyLen += NlMsgSize(nlMsgOutHdr); > + instance->dumpState.index[0] = dumpOutput.position[0]; > + instance->dumpState.index[1] = dumpOutput.position[1]; > + } > + } while(TRUE); > + > +done: > + return rc; > +} > + > +static NTSTATUS > +_MapFlowInfoToNl(PNL_BUFFER nlBuf, OvsFlowInfo *flowInfo) > +{ > + NTSTATUS rc = STATUS_SUCCESS; > + > + rc = _MapFlowKeyToNlKey(nlBuf, &(flowInfo->key)); > + if (rc != STATUS_SUCCESS) { > + OVS_LOG_ERROR("_MapFlowKeyToNlKey failed."); > + goto done; > + } > + > + rc = _MapFlowStatsToNlStats(nlBuf, &(flowInfo->stats)); > + if (rc != STATUS_SUCCESS) { > + OVS_LOG_ERROR("_OvsFlowMapFlowKeyToNlStats failed."); > + goto done; > + } > + > + rc = _MapFlowActionToNlAction(nlBuf, flowInfo->actionsLen, > + flowInfo->actions); > + if (rc != STATUS_SUCCESS) { > + OVS_LOG_ERROR("_MapFlowActionToNlAction failed."); > + goto done; > + } > + > +done: > + return rc; > +} > + > +static NTSTATUS > +_MapFlowStatsToNlStats(PNL_BUFFER nlBuf, OvsFlowStats *flowStats) > +{ > + NTSTATUS rc = STATUS_SUCCESS; > + struct ovs_flow_stats replyStats; > + > + replyStats.n_packets = flowStats->packetCount; > + replyStats.n_bytes = flowStats->byteCount; > + > + if (!NlMsgPutTailU64(nlBuf, OVS_FLOW_ATTR_USED, flowStats->used)) { > + OVS_LOG_ERROR("Adding OVS_FLOW_ATTR_USED attribute failed."); > + rc = STATUS_UNSUCCESSFUL; > + goto done; > + } > + > + if (!NlMsgPutTailUnspec(nlBuf, OVS_FLOW_ATTR_STATS, > + (PCHAR)(&replyStats), > + sizeof(struct ovs_flow_stats))) { > + OVS_LOG_ERROR("Adding OVS_FLOW_ATTR_STATS attribute failed."); > + rc = STATUS_UNSUCCESSFUL; > + goto done; > + } > + > + /* XXX: Verify if we need to htons here */ > + if (!NlMsgPutTailU8(nlBuf, OVS_FLOW_ATTR_TCP_FLAGS, > flowStats->tcpFlags)) { > + OVS_LOG_ERROR("Adding OVS_FLOW_ATTR_USED attribute failed."); > + rc = STATUS_UNSUCCESSFUL; > + goto done; > + } > + > +done: > + return rc; > +} > + > +static NTSTATUS > +_MapFlowActionToNlAction(PNL_BUFFER nlBuf, uint32_t actionsLen, > + PNL_ATTR actions) > +{ > + NTSTATUS rc = STATUS_SUCCESS; > + UINT32 offset = 0; > + > + offset = NlMsgStartNested(nlBuf, OVS_FLOW_ATTR_ACTIONS); > + if (!offset) { > + /* Starting the nested attribute failed. */ > + OVS_LOG_ERROR("Start Nested failed."); > + rc = STATUS_UNSUCCESSFUL; > + goto error_nested_start; > + } > + > + if (!NlBufCopyAtTail(nlBuf, (PCHAR)actions, actionsLen)) { > + /* Starting the nested attribute failed. */ Comment is wrong and probably redundant. > + OVS_LOG_ERROR("Copying the actions failed."); > + rc = STATUS_UNSUCCESSFUL; > + goto done; > + } > + > +done: > + NlMsgEndNested(nlBuf, offset); > +error_nested_start: > + return rc; > + > +} > + > +static NTSTATUS > +_MapFlowKeyToNlKey(PNL_BUFFER nlBuf, OvsFlowKey *flowKey) > +{ > + NTSTATUS rc = STATUS_SUCCESS; > + struct ovs_key_ethernet ethKey; > + UINT32 offset = 0; > + > + offset = NlMsgStartNested(nlBuf, OVS_FLOW_ATTR_KEY); > + if (!offset) { > + /* Starting the nested attribute failed. */ > + OVS_LOG_ERROR("Start Nested failed."); > + rc = STATUS_UNSUCCESSFUL; > + goto error_nested_start; > + } > + > + /* Ethernet header */ > + RtlCopyMemory(&(ethKey.eth_src), flowKey->l2.dlSrc, ETH_ADDR_LEN); > + RtlCopyMemory(&(ethKey.eth_dst), flowKey->l2.dlDst, ETH_ADDR_LEN); > + > + if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ETHERNET, > + (PCHAR)(ðKey), > + sizeof(struct ovs_key_ethernet))) { > + OVS_LOG_ERROR("Adding OVS_KEY_ATTR_ETHERNET attribute failed."); In each of the cases where we failed due to no buffer space, I am not sure if we need a OVS_LOG_ERROR(). In the future, when we have lots of flows, and all of them cannot be dumped at once, we'll end up seeing these logs at lot. This it not an issue for now, but just something to keep in mind for the future. > + rc = STATUS_UNSUCCESSFUL; > + goto done; > + } > + > + if (!NlMsgPutTailU32(nlBuf, OVS_KEY_ATTR_IN_PORT, > + flowKey->l2.inPort)) { > + OVS_LOG_ERROR("Adding OVS_KEY_ATTR_ETHERNET attribute failed."); > + rc = STATUS_UNSUCCESSFUL; > + goto done; > + } > + > + if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_ETHERTYPE, > + htons(flowKey->l2.dlType))) { > + OVS_LOG_ERROR("Adding OVS_KEY_ATTR_ETHERTYPE attribute failed."); > + rc = STATUS_UNSUCCESSFUL; > + goto done; > + } > + > + if (flowKey->l2.vlanTci) { > + if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_VLAN, > + flowKey->l2.vlanTci)) { > + OVS_LOG_ERROR("Adding OVS_KEY_ATTR_VLAN attribute failed."); > + rc = STATUS_UNSUCCESSFUL; > + goto done; > + } > + } > + > + /* ==== L3 + L4 ==== */ > + switch (flowKey->l2.dlType) { > + case ETH_TYPE_IPV4: { > + IpKey *ipv4FlowPutKey = &(flowKey->ipKey); > + rc = _MapFlowIpv4KeyToNlKey(nlBuf, ipv4FlowPutKey); > + break; > + } > + > + case ETH_TYPE_IPV6: { > + Ipv6Key *ipv6FlowPutKey = &(flowKey->ipv6Key); > + Icmp6Key *icmpv6FlowPutKey = &(flowKey->icmp6Key); > + rc = _MapFlowIpv6KeyToNlKey(nlBuf, ipv6FlowPutKey, > + icmpv6FlowPutKey); > + break; > + } > + > + case ETH_TYPE_ARP: > + case ETH_TYPE_RARP: { > + ArpKey *arpFlowPutKey = &(flowKey->arpKey); > + rc = _MapFlowArpKeyToNlKey(nlBuf, arpFlowPutKey); > + break; > + } > + > + default: > + break; > + } > + > + if (rc != STATUS_SUCCESS) { > + OVS_LOG_ERROR("Adding attributes for: %d failed.", > flowKey->l2.dlType); > + goto done; > + } > + > + if (flowKey->tunKey.dst) { > + rc = _MapFlowTunKeyToNlKey(nlBuf, &(flowKey->tunKey)); > + if (rc != STATUS_SUCCESS) { > + goto done; > + } > + } > + > +done: > + NlMsgEndNested(nlBuf, offset); > +error_nested_start: > + return rc; > +} > + > +static NTSTATUS > +_MapFlowTunKeyToNlKey(PNL_BUFFER nlBuf, OvsIPv4TunnelKey *tunKey) > +{ > + NTSTATUS rc = STATUS_SUCCESS; > + UINT32 offset = 0; > + > + offset = NlMsgStartNested(nlBuf, OVS_KEY_ATTR_TUNNEL); > + if (!offset) { > + /* Starting the nested attribute failed. */ > + OVS_LOG_ERROR("Start Nested failed."); > + rc = STATUS_UNSUCCESSFUL; > + goto error_nested_start; > + } > + > + if (!NlMsgPutTailU64(nlBuf, OVS_TUNNEL_KEY_ATTR_ID, > + tunKey->tunnelId)) { > + OVS_LOG_ERROR("Adding OVS_TUNNEL_KEY_ATTR_ID attribute failed."); > + rc = STATUS_UNSUCCESSFUL; > + goto done; > + } > + > + if (!NlMsgPutTailU32(nlBuf, OVS_TUNNEL_KEY_ATTR_IPV4_DST, > + tunKey->dst)) { > + OVS_LOG_ERROR("Adding OVS_TUNNEL_KEY_ATTR_IPV4_DST attribute > failed."); > + rc = STATUS_UNSUCCESSFUL; > + goto done; > + } > + > + if (!NlMsgPutTailU32(nlBuf, OVS_TUNNEL_KEY_ATTR_IPV4_SRC, > + tunKey->src)) { > + OVS_LOG_ERROR("Adding OVS_TUNNEL_KEY_ATTR_IPV4_SRC attribute > failed."); > + rc = STATUS_UNSUCCESSFUL; > + goto done; > + } > + > + if (!NlMsgPutTailU8(nlBuf, OVS_TUNNEL_KEY_ATTR_TOS, > + tunKey->tos)) { > + OVS_LOG_ERROR("Adding OVS_TUNNEL_KEY_ATTR_TOS attribute failed."); > + rc = STATUS_UNSUCCESSFUL; > + goto done; > + } > + > + if (!NlMsgPutTailU8(nlBuf, OVS_TUNNEL_KEY_ATTR_TTL, > + tunKey->ttl)) { > + OVS_LOG_ERROR("Adding OVS_TUNNEL_KEY_ATTR_TTL attribute failed."); > + rc = STATUS_UNSUCCESSFUL; > + goto done; > + } > + > +done: > + NlMsgEndNested(nlBuf, offset); > +error_nested_start: > + return rc; > +} > + > +static NTSTATUS > +_MapFlowIpv4KeyToNlKey(PNL_BUFFER nlBuf, IpKey *ipv4FlowPutKey) > +{ > + NTSTATUS rc = STATUS_SUCCESS; > + struct ovs_key_ipv4 ipv4Key; > + > + ipv4Key.ipv4_src = ipv4FlowPutKey->nwSrc; > + ipv4Key.ipv4_dst = ipv4FlowPutKey->nwDst; > + ipv4Key.ipv4_proto = ipv4FlowPutKey->nwProto; > + ipv4Key.ipv4_tos = ipv4FlowPutKey->nwTos; > + ipv4Key.ipv4_ttl = ipv4FlowPutKey->nwTtl; > + ipv4Key.ipv4_frag = ipv4FlowPutKey->nwFrag; > + > + if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_IPV4, > + (PCHAR)(&ipv4Key), > + sizeof(struct ovs_key_ipv4))) { > + OVS_LOG_ERROR("Adding OVS_KEY_ATTR_IPV4 attribute failed."); > + rc = STATUS_UNSUCCESSFUL; > + goto done; > + } > + > + switch (ipv4Key.ipv4_proto) { > + case IPPROTO_TCP: { > + struct ovs_key_tcp tcpKey; > + tcpKey.tcp_src = ipv4FlowPutKey->l4.tpSrc; > + tcpKey.tcp_dst = ipv4FlowPutKey->l4.tpDst; > + if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_TCP, > + (PCHAR)(&tcpKey), > + sizeof(struct ovs_key_tcp))) { Minor: can you use sizeof tcpKey? > + OVS_LOG_ERROR("Adding OVS_KEY_ATTR_TCP attribute failed."); > + rc = STATUS_UNSUCCESSFUL; > + goto done; > + } > + break; > + } > + > + case IPPROTO_UDP: { > + struct ovs_key_udp udpKey; > + udpKey.udp_src = ipv4FlowPutKey->l4.tpSrc; > + udpKey.udp_dst = ipv4FlowPutKey->l4.tpDst; > + if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_UDP, > + (PCHAR)(&udpKey), > + sizeof(struct ovs_key_udp))) { Minor: can you use sizeof udpKey? > + OVS_LOG_ERROR("Adding OVS_KEY_ATTR_UDP attribute failed."); > + rc = STATUS_UNSUCCESSFUL; > + goto done; > + } > + break; > + } > + > + case IPPROTO_SCTP: { > + struct ovs_key_sctp sctpKey; > + sctpKey.sctp_src = ipv4FlowPutKey->l4.tpSrc; > + sctpKey.sctp_dst = ipv4FlowPutKey->l4.tpDst; > + if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_SCTP, > + (PCHAR)(&sctpKey), > + sizeof(struct ovs_key_sctp))) { Minor: can you use sizeof sctpKey? > + OVS_LOG_ERROR("Adding OVS_KEY_ATTR_SCTP attribute failed."); > + rc = STATUS_UNSUCCESSFUL; > + goto done; > + } > + break; > + } > + > + case IPPROTO_ICMP: { > + struct ovs_key_icmp icmpKey; > + /* XXX: revisit to see if htons is needed */ > + icmpKey.icmp_type = (__u8)(ipv4FlowPutKey->l4.tpSrc); > + icmpKey.icmp_code = (__u8)(ipv4FlowPutKey->l4.tpDst); > + > + if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ICMP, > + (PCHAR)(&icmpKey), > + sizeof(struct ovs_key_icmp))) { > + OVS_LOG_ERROR("Adding OVS_KEY_ATTR_ICMP attribute failed."); > + rc = STATUS_UNSUCCESSFUL; > + goto done; > + } > + break; > + } > + > + default: You can ASSERT here, since such a flow should have not been added to the kernel. > + break; > + } > + > +done: > + return rc; > +} > + > +static NTSTATUS > +_MapFlowIpv6KeyToNlKey(PNL_BUFFER nlBuf, Ipv6Key *ipv6FlowPutKey, > + Icmp6Key *icmpv6FlowPutKey) > +{ > + NTSTATUS rc = STATUS_SUCCESS; > + struct ovs_key_ipv6 ipv6Key; > + > + RtlCopyMemory(&(ipv6Key.ipv6_src), &ipv6FlowPutKey->ipv6Src, > + sizeof ipv6Key.ipv6_src); > + RtlCopyMemory(&(ipv6Key.ipv6_dst), &ipv6FlowPutKey->ipv6Dst, > + sizeof ipv6Key.ipv6_dst); > + > + ipv6Key.ipv6_label = ipv6FlowPutKey->ipv6Label; > + ipv6Key.ipv6_proto = ipv6FlowPutKey->nwProto; > + ipv6Key.ipv6_tclass = ipv6FlowPutKey->nwTos; > + ipv6Key.ipv6_hlimit = ipv6FlowPutKey->nwTtl; > + ipv6Key.ipv6_frag = ipv6FlowPutKey->nwFrag; > + > + if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_IPV6, > + (PCHAR)(&ipv6Key), > + sizeof(struct ovs_key_ipv6))) { > + OVS_LOG_ERROR("Adding OVS_KEY_ATTR_IPV6 attribute failed."); > + rc = STATUS_UNSUCCESSFUL; > + goto done; > + } > + > + switch (ipv6Key.ipv6_proto) { > + case IPPROTO_TCP: { > + struct ovs_key_tcp tcpKey; > + tcpKey.tcp_src = ipv6FlowPutKey->l4.tpSrc; > + tcpKey.tcp_dst = ipv6FlowPutKey->l4.tpDst; > + if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_TCP, > + (PCHAR)(&tcpKey), > + sizeof(struct ovs_key_tcp))) { > + OVS_LOG_ERROR("Adding OVS_KEY_ATTR_TCP attribute failed."); > + rc = STATUS_UNSUCCESSFUL; > + goto done; > + } > + break; > + } > + > + case IPPROTO_UDP: { > + struct ovs_key_udp udpKey; > + udpKey.udp_src = ipv6FlowPutKey->l4.tpSrc; > + udpKey.udp_dst = ipv6FlowPutKey->l4.tpDst; > + if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_UDP, > + (PCHAR)(&udpKey), > + sizeof(struct ovs_key_udp))) { > + OVS_LOG_ERROR("Adding OVS_KEY_ATTR_UDP attribute failed."); > + rc = STATUS_UNSUCCESSFUL; > + goto done; > + } > + break; > + } > + > + case IPPROTO_SCTP: { > + struct ovs_key_sctp sctpKey; > + sctpKey.sctp_src = ipv6FlowPutKey->l4.tpSrc; > + sctpKey.sctp_dst = ipv6FlowPutKey->l4.tpDst; > + if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_SCTP, > + (PCHAR)(&sctpKey), > + sizeof(struct ovs_key_sctp))) { > + OVS_LOG_ERROR("Adding OVS_KEY_ATTR_SCTP attribute failed."); > + rc = STATUS_UNSUCCESSFUL; > + goto done; > + } > + break; > + } > + > + case IPPROTO_ICMPV6: { > + struct ovs_key_icmpv6 icmpV6Key; > + struct ovs_key_nd ndKey; > + > + /* XXX: revisit to see if htons is needed */ Generally, we don't need htons conversion since the flow key is always in N/W byte order. > + icmpV6Key.icmpv6_type = (__u8)(icmpv6FlowPutKey->l4.tpSrc); > + icmpV6Key.icmpv6_code = (__u8)(icmpv6FlowPutKey->l4.tpDst); > + > + if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ICMPV6, > + (PCHAR)(&icmpV6Key), > + sizeof(struct ovs_key_icmpv6))) { > + OVS_LOG_ERROR("Adding OVS_KEY_ATTR_ICMPV6 attribute > failed."); > + rc = STATUS_UNSUCCESSFUL; > + goto done; > + } > + > + RtlCopyMemory(&(ndKey.nd_target), &icmpv6FlowPutKey->ndTarget, > + sizeof(icmpv6FlowPutKey->ndTarget)); > + RtlCopyMemory(&(ndKey.nd_sll), &icmpv6FlowPutKey->arpSha, > + ETH_ADDR_LEN); > + RtlCopyMemory(&(ndKey.nd_tll), &icmpv6FlowPutKey->arpTha, > + ETH_ADDR_LEN); > + if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ND, > + (PCHAR)(&ndKey), > + sizeof(struct ovs_key_nd))) { > + OVS_LOG_ERROR("Adding OVS_KEY_ATTR_ND attribute failed."); > + rc = STATUS_UNSUCCESSFUL; > + goto done; > + } > + > + break; > + } > + > + default: > + break; > + } > + > +done: > + return rc; > +} > + > +static NTSTATUS > +_MapFlowArpKeyToNlKey(PNL_BUFFER nlBuf, ArpKey *arpFlowPutKey) > +{ > + NTSTATUS rc = STATUS_SUCCESS; > + struct ovs_key_arp arpKey; > + > + arpKey.arp_sip = arpFlowPutKey->nwSrc; > + arpKey.arp_tip = arpFlowPutKey->nwDst; > + > + RtlCopyMemory(&(arpKey.arp_sha), arpFlowPutKey->arpSha, ETH_ADDR_LEN); > + RtlCopyMemory(&(arpKey.arp_tha), arpFlowPutKey->arpTha, ETH_ADDR_LEN); > + > + arpKey.arp_op = arpFlowPutKey->nwProto; > + > + if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ARP, > + (PCHAR)(&arpKey), > + sizeof(struct ovs_key_arp))) { > + OVS_LOG_ERROR("Adding OVS_KEY_ATTR_ARP attribute failed."); > + rc = STATUS_UNSUCCESSFUL; > + goto done; > + } > + > +done: > return rc; > } > > @@ -1202,8 +1822,7 @@ OvsDoDumpFlows(OvsFlowDumpInput *dumpInput, > ASSERT(rowIndex < OVS_FLOW_TABLE_SIZE); > > flow = CONTAINING_RECORD(node, OvsFlow, ListEntry); > - status = ReportFlowInfo(flow, dumpInput->getFlags, dumpInput->actionsLen, > - > &dumpOutput->flow); > + status = ReportFlowInfo(flow, dumpInput->getFlags, &dumpOutput->flow); > > if (status == STATUS_BUFFER_TOO_SMALL) { > dumpOutput->n = sizeof(OvsFlowDumpOutput) + flow->actionsLen; > @@ -1249,7 +1868,6 @@ OvsDumpFlowIoctl(PVOID inputBuffer, > static NTSTATUS > ReportFlowInfo(OvsFlow *flow, > UINT32 getFlags, > - UINT32 getActionsLen, > OvsFlowInfo *info) > { > NTSTATUS status = STATUS_SUCCESS; > @@ -1271,11 +1889,8 @@ ReportFlowInfo(OvsFlow *flow, > if (getFlags & FLOW_GET_ACTIONS) { > if (flow->actionsLen == 0) { > info->actionsLen = 0; > - } else if (flow->actionsLen > getActionsLen) { > - info->actionsLen = 0; > - status = STATUS_BUFFER_TOO_SMALL; > } else { > - RtlCopyMemory(info->actions, flow->actions, flow->actionsLen); > + info->actions = flow->actions; > info->actionsLen = flow->actionsLen; > } > } > @@ -1518,7 +2133,7 @@ OvsGetFlowIoctl(PVOID inputBuffer, > // XXX: can be optimized to return only how much is written out > *replyLen = outputLength; > getOutput = (OvsFlowGetOutput *)outputBuffer; > - ReportFlowInfo(flow, getFlags, getActionsLen, &getOutput->info); > + ReportFlowInfo(flow, getFlags, &getOutput->info); > > dp_unlock: > OvsReleaseDatapath(datapath, &dpLockState); > -- > 1.9.1 > > _______________________________________________ > dev mailing list > dev@openvswitch.org > https://urldefense.proofpoint.com/v1/url?u=http://openvswitch.org/mailman/listinfo/dev&k=oIvRg1%2BdGAgOoM1BIlLLqw%3D%3D%0A&r=ubrOpIWavCMqX4l4j1LEVpTfDj%2FD5Qyn8KCoJIBGvzo%3D%0A&m=qmAM%2FTms%2FFewcVKx08wgK6mhysN8n0MMspnuFR2xR2Q%3D%0A&s=9e52feae85e09f899f423e260f99fbbd43669a8be485baaa6a3fd88e1bf2c6ff Thanks, -- Nithin _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev