2 * Copyright (c) 2014 VMware, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
31 #define OVS_DBG_MOD OVS_DBG_VPORT
34 #define VPORT_NIC_ENTER(_nic) \
35 OVS_LOG_TRACE("Enter: PortId: %x, NicIndex: %d", _nic->PortId, \
38 #define VPORT_NIC_EXIT(_nic) \
39 OVS_LOG_TRACE("Exit: PortId: %x, NicIndex: %d", _nic->PortId, \
42 #define VPORT_PORT_ENTER(_port) \
43 OVS_LOG_TRACE("Enter: PortId: %x", _port->PortId)
45 #define VPORT_PORT_EXIT(_port) \
46 OVS_LOG_TRACE("Exit: PortId: %x", _port->PortId)
48 #define OVS_VPORT_DEFAULT_WAIT_TIME_MICROSEC 100
50 extern POVS_SWITCH_CONTEXT gOvsSwitchContext;
51 extern PNDIS_SPIN_LOCK gOvsCtrlLock;
53 static UINT32 OvsGetVportNo(POVS_SWITCH_CONTEXT switchContext, UINT32 nicIndex,
54 OVS_VPORT_TYPE ovsType,
56 static POVS_VPORT_ENTRY OvsAllocateVport(VOID);
57 static VOID OvsInitVportWithPortParam(POVS_VPORT_ENTRY vport,
58 PNDIS_SWITCH_PORT_PARAMETERS portParam);
59 static VOID OvsInitVportWithNicParam(POVS_SWITCH_CONTEXT switchContext,
60 POVS_VPORT_ENTRY vport, PNDIS_SWITCH_NIC_PARAMETERS nicParam);
61 static VOID OvsInitPhysNicVport(POVS_VPORT_ENTRY vport, POVS_VPORT_ENTRY
62 virtVport, UINT32 nicIndex);
63 static VOID OvsInitPhysNicVport(POVS_VPORT_ENTRY vport, POVS_VPORT_ENTRY
64 virtVport, UINT32 nicIndex);
65 static NDIS_STATUS OvsInitVportCommon(POVS_SWITCH_CONTEXT switchContext,
66 POVS_VPORT_ENTRY vport);
67 static VOID OvsRemoveAndDeleteVport(POVS_SWITCH_CONTEXT switchContext,
68 POVS_VPORT_ENTRY vport);
69 static __inline VOID OvsWaitActivate(POVS_SWITCH_CONTEXT switchContext,
71 static NTSTATUS OvsGetExtInfoIoctl(POVS_VPORT_GET vportGet,
72 POVS_VPORT_EXT_INFO extInfo);
73 static NTSTATUS CreateNetlinkMesgForNetdev(POVS_VPORT_EXT_INFO info,
80 * Functions implemented in relaton to NDIS port manipulation.
83 OvsCreatePort(POVS_SWITCH_CONTEXT switchContext,
84 PNDIS_SWITCH_PORT_PARAMETERS portParam)
86 POVS_VPORT_ENTRY vport;
87 LOCK_STATE_EX lockState;
88 NDIS_STATUS status = NDIS_STATUS_SUCCESS;
90 VPORT_PORT_ENTER(portParam);
92 NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0);
93 vport = OvsFindVportByPortIdAndNicIndex(switchContext,
94 portParam->PortId, 0);
96 status = STATUS_DATA_NOT_ACCEPTED;
97 goto create_port_done;
99 vport = (POVS_VPORT_ENTRY)OvsAllocateVport();
101 status = NDIS_STATUS_RESOURCES;
102 goto create_port_done;
104 OvsInitVportWithPortParam(vport, portParam);
105 OvsInitVportCommon(switchContext, vport);
108 NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
109 VPORT_PORT_EXIT(portParam);
114 OvsTeardownPort(POVS_SWITCH_CONTEXT switchContext,
115 PNDIS_SWITCH_PORT_PARAMETERS portParam)
117 POVS_VPORT_ENTRY vport;
118 LOCK_STATE_EX lockState;
120 VPORT_PORT_ENTER(portParam);
122 NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0);
123 vport = OvsFindVportByPortIdAndNicIndex(switchContext,
124 portParam->PortId, 0);
126 /* add assertion here
128 vport->portState = NdisSwitchPortStateTeardown;
129 vport->ovsState = OVS_STATE_PORT_TEAR_DOWN;
131 OVS_LOG_WARN("Vport not present.");
133 NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
135 VPORT_PORT_EXIT(portParam);
141 OvsDeletePort(POVS_SWITCH_CONTEXT switchContext,
142 PNDIS_SWITCH_PORT_PARAMETERS portParam)
144 POVS_VPORT_ENTRY vport;
145 LOCK_STATE_EX lockState;
147 VPORT_PORT_ENTER(portParam);
149 NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0);
150 vport = OvsFindVportByPortIdAndNicIndex(switchContext,
151 portParam->PortId, 0);
153 OvsRemoveAndDeleteVport(switchContext, vport);
155 OVS_LOG_WARN("Vport not present.");
157 NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
159 VPORT_PORT_EXIT(portParam);
164 * Functions implemented in relaton to NDIS NIC manipulation.
167 OvsCreateNic(POVS_SWITCH_CONTEXT switchContext,
168 PNDIS_SWITCH_NIC_PARAMETERS nicParam)
170 POVS_VPORT_ENTRY vport;
173 NDIS_STATUS status = NDIS_STATUS_SUCCESS;
175 LOCK_STATE_EX lockState;
177 VPORT_NIC_ENTER(nicParam);
179 /* Wait for lists to be initialized. */
180 OvsWaitActivate(switchContext, OVS_VPORT_DEFAULT_WAIT_TIME_MICROSEC);
182 if (!switchContext->isActivated) {
183 OVS_LOG_WARN("Switch is not activated yet.");
184 /* Veto the creation of nic */
185 status = NDIS_STATUS_NOT_SUPPORTED;
189 NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0);
190 vport = OvsFindVportByPortIdAndNicIndex(switchContext, nicParam->PortId, 0);
192 OVS_LOG_ERROR("Create NIC without Switch Port,"
193 " PortId: %x, NicIndex: %d",
194 nicParam->PortId, nicParam->NicIndex);
195 status = NDIS_STATUS_INVALID_PARAMETER;
199 if (nicParam->NicType == NdisSwitchNicTypeExternal &&
200 nicParam->NicIndex != 0) {
201 POVS_VPORT_ENTRY virtVport =
202 (POVS_VPORT_ENTRY)switchContext->externalVport;
203 vport = (POVS_VPORT_ENTRY)OvsAllocateVport();
205 status = NDIS_STATUS_RESOURCES;
208 OvsInitPhysNicVport(vport, virtVport, nicParam->NicIndex);
209 status = OvsInitVportCommon(switchContext, vport);
210 if (status != NDIS_STATUS_SUCCESS) {
211 OvsFreeMemory(vport);
215 OvsInitVportWithNicParam(switchContext, vport, nicParam);
216 portNo = vport->portNo;
217 if (vport->ovsState == OVS_STATE_CONNECTED) {
218 event = OVS_EVENT_CONNECT | OVS_EVENT_LINK_UP;
219 } else if (vport->ovsState == OVS_STATE_NIC_CREATED) {
220 event = OVS_EVENT_CONNECT;
224 NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
225 if (portNo && event) {
226 OvsPostEvent(portNo, event);
230 VPORT_NIC_EXIT(nicParam);
231 OVS_LOG_TRACE("Exit: status %8x.\n", status);
237 /* Mark already created NIC as connected. */
239 OvsConnectNic(POVS_SWITCH_CONTEXT switchContext,
240 PNDIS_SWITCH_NIC_PARAMETERS nicParam)
242 LOCK_STATE_EX lockState;
243 POVS_VPORT_ENTRY vport;
246 VPORT_NIC_ENTER(nicParam);
248 /* Wait for lists to be initialized. */
249 OvsWaitActivate(switchContext, OVS_VPORT_DEFAULT_WAIT_TIME_MICROSEC);
251 if (!switchContext->isActivated) {
252 OVS_LOG_WARN("Switch is not activated yet.");
256 NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0);
257 vport = OvsFindVportByPortIdAndNicIndex(switchContext,
262 OVS_LOG_WARN("Vport not present.");
263 NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
268 vport->ovsState = OVS_STATE_CONNECTED;
269 vport->nicState = NdisSwitchNicStateConnected;
270 portNo = vport->portNo;
272 NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
274 OvsPostEvent(portNo, OVS_EVENT_LINK_UP);
276 if (nicParam->NicType == NdisSwitchNicTypeInternal) {
277 OvsInternalAdapterUp(portNo, &nicParam->NetCfgInstanceId);
281 VPORT_NIC_EXIT(nicParam);
285 OvsUpdateNic(POVS_SWITCH_CONTEXT switchContext,
286 PNDIS_SWITCH_NIC_PARAMETERS nicParam)
288 POVS_VPORT_ENTRY vport;
289 LOCK_STATE_EX lockState;
291 UINT32 status = 0, portNo = 0;
293 VPORT_NIC_ENTER(nicParam);
295 /* Wait for lists to be initialized. */
296 OvsWaitActivate(switchContext, OVS_VPORT_DEFAULT_WAIT_TIME_MICROSEC);
298 if (!switchContext->isActivated) {
299 OVS_LOG_WARN("Switch is not activated yet.");
300 goto update_nic_done;
303 NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0);
304 vport = OvsFindVportByPortIdAndNicIndex(switchContext,
308 OVS_LOG_WARN("Vport search failed.");
309 goto update_nic_done;
311 switch (nicParam->NicType) {
312 case NdisSwitchNicTypeExternal:
313 case NdisSwitchNicTypeInternal:
314 RtlCopyMemory(&vport->netCfgInstanceId, &nicParam->NetCfgInstanceId,
317 case NdisSwitchNicTypeSynthetic:
318 case NdisSwitchNicTypeEmulated:
319 if (!RtlEqualMemory(vport->vmMacAddress, nicParam->VMMacAddress,
320 sizeof (vport->vmMacAddress))) {
321 status |= OVS_EVENT_MAC_CHANGE;
322 RtlCopyMemory(vport->vmMacAddress, nicParam->VMMacAddress,
323 sizeof (vport->vmMacAddress));
329 if (!RtlEqualMemory(vport->permMacAddress, nicParam->PermanentMacAddress,
330 sizeof (vport->permMacAddress))) {
331 RtlCopyMemory(vport->permMacAddress, nicParam->PermanentMacAddress,
332 sizeof (vport->permMacAddress));
333 status |= OVS_EVENT_MAC_CHANGE;
335 if (!RtlEqualMemory(vport->currMacAddress, nicParam->CurrentMacAddress,
336 sizeof (vport->currMacAddress))) {
337 RtlCopyMemory(vport->currMacAddress, nicParam->CurrentMacAddress,
338 sizeof (vport->currMacAddress));
339 status |= OVS_EVENT_MAC_CHANGE;
342 if (vport->mtu != nicParam->MTU) {
343 vport->mtu = nicParam->MTU;
344 status |= OVS_EVENT_MTU_CHANGE;
346 vport->numaNodeId = nicParam->NumaNodeId;
347 portNo = vport->portNo;
349 NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
350 if (status && portNo) {
351 OvsPostEvent(portNo, status);
354 VPORT_NIC_EXIT(nicParam);
359 OvsDisconnectNic(POVS_SWITCH_CONTEXT switchContext,
360 PNDIS_SWITCH_NIC_PARAMETERS nicParam)
362 POVS_VPORT_ENTRY vport;
364 LOCK_STATE_EX lockState;
365 BOOLEAN isInternalPort = FALSE;
367 VPORT_NIC_ENTER(nicParam);
369 /* Wait for lists to be initialized. */
370 OvsWaitActivate(switchContext, OVS_VPORT_DEFAULT_WAIT_TIME_MICROSEC);
372 if (!switchContext->isActivated) {
373 OVS_LOG_WARN("Switch is not activated yet.");
377 NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0);
378 vport = OvsFindVportByPortIdAndNicIndex(switchContext,
383 OVS_LOG_WARN("Vport not present.");
384 NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
388 vport->nicState = NdisSwitchNicStateDisconnected;
389 vport->ovsState = OVS_STATE_NIC_CREATED;
390 portNo = vport->portNo;
392 if (vport->ovsType == OVS_VPORT_TYPE_INTERNAL) {
393 isInternalPort = TRUE;
396 NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
398 OvsPostEvent(portNo, OVS_EVENT_LINK_DOWN);
400 if (isInternalPort) {
401 OvsInternalAdapterDown();
405 VPORT_NIC_EXIT(nicParam);
410 OvsDeleteNic(POVS_SWITCH_CONTEXT switchContext,
411 PNDIS_SWITCH_NIC_PARAMETERS nicParam)
413 LOCK_STATE_EX lockState;
414 POVS_VPORT_ENTRY vport;
417 VPORT_NIC_ENTER(nicParam);
418 /* Wait for lists to be initialized. */
419 OvsWaitActivate(switchContext, OVS_VPORT_DEFAULT_WAIT_TIME_MICROSEC);
421 if (!switchContext->isActivated) {
422 OVS_LOG_WARN("Switch is not activated yet.");
426 NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0);
427 vport = OvsFindVportByPortIdAndNicIndex(switchContext,
432 OVS_LOG_WARN("Vport not present.");
433 NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
437 portNo = vport->portNo;
438 if (vport->portType == NdisSwitchPortTypeExternal &&
439 vport->nicIndex != 0) {
440 OvsRemoveAndDeleteVport(switchContext, vport);
442 vport->nicState = NdisSwitchNicStateUnknown;
443 vport->ovsState = OVS_STATE_PORT_CREATED;
445 NdisReleaseRWLock(switchContext->dispatchLock, &lockState);
446 OvsPostEvent(portNo, OVS_EVENT_DISCONNECT);
449 VPORT_NIC_EXIT(nicParam);
454 * OVS Vport related functionality.
457 OvsFindVportByPortNo(POVS_SWITCH_CONTEXT switchContext,
460 if (OVS_VPORT_INDEX(portNo) < OVS_MAX_VPORT_ARRAY_SIZE) {
461 if (OVS_IS_VPORT_ENTRY_NULL(switchContext, OVS_VPORT_INDEX(portNo))) {
464 POVS_VPORT_ENTRY vport;
465 vport = (POVS_VPORT_ENTRY)
466 switchContext->vportArray[OVS_VPORT_INDEX(portNo)];
467 return vport->portNo == portNo ? vport : NULL;
475 OvsFindVportByOvsName(POVS_SWITCH_CONTEXT switchContext,
479 POVS_VPORT_ENTRY vport;
480 PLIST_ENTRY head, link;
481 UINT32 hash = OvsJhashBytes((const VOID *)name, length, OVS_HASH_BASIS);
482 head = &(switchContext->nameHashArray[hash & OVS_VPORT_MASK]);
483 LIST_FORALL(head, link) {
484 vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, nameLink);
485 if (vport->ovsNameLen == length &&
486 RtlEqualMemory(name, vport->ovsName, length)) {
494 OvsFindVportByPortIdAndNicIndex(POVS_SWITCH_CONTEXT switchContext,
495 NDIS_SWITCH_PORT_ID portId,
496 NDIS_SWITCH_NIC_INDEX index)
498 if (portId == switchContext->externalPortId) {
500 return (POVS_VPORT_ENTRY)switchContext->externalVport;
501 } else if (index > OVS_MAX_PHYS_ADAPTERS) {
504 if (OVS_IS_VPORT_ENTRY_NULL(switchContext,
505 index + OVS_EXTERNAL_VPORT_START)) {
508 return (POVS_VPORT_ENTRY)switchContext->vportArray[
509 index + OVS_EXTERNAL_VPORT_START];
511 } else if (switchContext->internalPortId == portId) {
512 return (POVS_VPORT_ENTRY)switchContext->internalVport;
514 PLIST_ENTRY head, link;
515 POVS_VPORT_ENTRY vport;
517 hash = OvsJhashWords((UINT32 *)&portId, 1, OVS_HASH_BASIS);
518 head = &(switchContext->portHashArray[hash & OVS_VPORT_MASK]);
519 LIST_FORALL(head, link) {
520 vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, portLink);
521 if (portId == vport->portId && index == vport->nicIndex) {
530 OvsGetVportNo(POVS_SWITCH_CONTEXT switchContext,
532 OVS_VPORT_TYPE ovsType,
535 UINT32 index = 0xffffff, i = 0;
540 return 0; // not a valid portNo
541 } else if (nicIndex > OVS_MAX_PHYS_ADAPTERS) {
544 index = nicIndex + OVS_EXTERNAL_VPORT_START;
549 case OVS_VPORT_TYPE_INTERNAL:
550 index = OVS_INTERNAL_VPORT_DEFAULT_INDEX;
552 case OVS_VPORT_TYPE_NETDEV:
553 index = switchContext->lastPortIndex + 1;
554 if (index == OVS_MAX_VPORT_ARRAY_SIZE) {
555 index = OVS_VM_VPORT_START;
557 while (!OVS_IS_VPORT_ENTRY_NULL(switchContext, index) &&
558 i < (OVS_MAX_VPORT_ARRAY_SIZE - OVS_VM_VPORT_START)) {
561 if (index == OVS_MAX_VPORT_ARRAY_SIZE) {
562 index = OVS_VM_VPORT_START;
565 if (i == (OVS_MAX_VPORT_ARRAY_SIZE - OVS_VM_VPORT_START)) {
566 return 0; // not available
568 switchContext->lastPortIndex = index;
570 case OVS_VPORT_TYPE_GRE:
571 index = OVS_GRE_VPORT_INDEX;
573 case OVS_VPORT_TYPE_GRE64:
574 index = OVS_GRE64_VPORT_INDEX;
576 case OVS_VPORT_TYPE_VXLAN:
577 index = OVS_VXLAN_VPORT_INDEX;
582 if (index > OVS_MAX_VPORT_ARRAY_SIZE) {
585 gen = (UINT64)switchContext->vportArray[index];
588 } else if (gen == 0) {
591 return OVS_VPORT_PORT_NO(index, (UINT32)gen);
595 static POVS_VPORT_ENTRY
596 OvsAllocateVport(VOID)
598 POVS_VPORT_ENTRY vport;
599 vport = (POVS_VPORT_ENTRY)OvsAllocateMemory(sizeof (OVS_VPORT_ENTRY));
603 RtlZeroMemory(vport, sizeof (OVS_VPORT_ENTRY));
604 vport->ovsState = OVS_STATE_UNKNOWN;
609 OvsInitVportWithPortParam(POVS_VPORT_ENTRY vport,
610 PNDIS_SWITCH_PORT_PARAMETERS portParam)
612 vport->isValidationPort = portParam->IsValidationPort;
613 vport->portType = portParam->PortType;
614 vport->portState = portParam->PortState;
615 vport->portId = portParam->PortId;
616 vport->nicState = NdisSwitchNicStateUnknown;
617 vport->isExternal = FALSE;
619 switch (vport->portType) {
620 case NdisSwitchPortTypeExternal:
621 vport->isExternal = TRUE;
622 vport->ovsType = OVS_VPORT_TYPE_NETDEV;
624 case NdisSwitchPortTypeInternal:
625 vport->ovsType = OVS_VPORT_TYPE_INTERNAL;
627 case NdisSwitchPortTypeSynthetic:
628 case NdisSwitchPortTypeEmulated:
629 vport->ovsType = OVS_VPORT_TYPE_NETDEV;
632 RtlCopyMemory(&vport->portName, &portParam->PortName,
633 sizeof (NDIS_SWITCH_PORT_NAME));
634 switch (vport->portState) {
635 case NdisSwitchPortStateCreated:
636 vport->ovsState = OVS_STATE_PORT_CREATED;
638 case NdisSwitchPortStateTeardown:
639 vport->ovsState = OVS_STATE_PORT_TEAR_DOWN;
641 case NdisSwitchPortStateDeleted:
642 vport->ovsState = OVS_STATE_PORT_DELETED;
649 OvsInitVportWithNicParam(POVS_SWITCH_CONTEXT switchContext,
650 POVS_VPORT_ENTRY vport,
651 PNDIS_SWITCH_NIC_PARAMETERS nicParam)
653 ASSERT(vport->portId == nicParam->PortId);
654 ASSERT(vport->ovsState == OVS_STATE_PORT_CREATED);
656 UNREFERENCED_PARAMETER(switchContext);
658 RtlCopyMemory(vport->permMacAddress, nicParam->PermanentMacAddress,
659 sizeof (nicParam->PermanentMacAddress));
660 RtlCopyMemory(vport->currMacAddress, nicParam->CurrentMacAddress,
661 sizeof (nicParam->CurrentMacAddress));
663 if (nicParam->NicType == NdisSwitchNicTypeSynthetic ||
664 nicParam->NicType == NdisSwitchNicTypeEmulated) {
665 RtlCopyMemory(vport->vmMacAddress, nicParam->VMMacAddress,
666 sizeof (nicParam->VMMacAddress));
667 RtlCopyMemory(&vport->vmName, &nicParam->VmName,
668 sizeof (nicParam->VmName));
670 RtlCopyMemory(&vport->netCfgInstanceId, &nicParam->NetCfgInstanceId,
671 sizeof (nicParam->NetCfgInstanceId));
673 RtlCopyMemory(&vport->nicName, &nicParam->NicName,
674 sizeof (nicParam->NicName));
675 vport->mtu = nicParam->MTU;
676 vport->nicState = nicParam->NicState;
677 vport->nicIndex = nicParam->NicIndex;
678 vport->numaNodeId = nicParam->NumaNodeId;
680 switch (vport->nicState) {
681 case NdisSwitchNicStateCreated:
682 vport->ovsState = OVS_STATE_NIC_CREATED;
684 case NdisSwitchNicStateConnected:
685 vport->ovsState = OVS_STATE_CONNECTED;
687 case NdisSwitchNicStateDisconnected:
688 vport->ovsState = OVS_STATE_NIC_CREATED;
690 case NdisSwitchNicStateDeleted:
691 vport->ovsState = OVS_STATE_PORT_CREATED;
697 OvsInitPhysNicVport(POVS_VPORT_ENTRY vport,
698 POVS_VPORT_ENTRY virtVport,
701 vport->isValidationPort = virtVport->isValidationPort;
702 vport->portType = virtVport->portType;
703 vport->portState = virtVport->portState;
704 vport->portId = virtVport->portId;
705 vport->nicState = NdisSwitchNicStateUnknown;
706 vport->ovsType = OVS_VPORT_TYPE_NETDEV;
707 vport->isExternal = TRUE;
708 vport->nicIndex = (NDIS_SWITCH_NIC_INDEX)nicIndex;
709 RtlCopyMemory(&vport->portName, &virtVport->portName,
710 sizeof (NDIS_SWITCH_PORT_NAME));
711 vport->ovsState = OVS_STATE_PORT_CREATED;
714 OvsInitVportCommon(POVS_SWITCH_CONTEXT switchContext,
715 POVS_VPORT_ENTRY vport)
719 if (vport->portType != NdisSwitchPortTypeExternal ||
720 vport->nicIndex != 0) {
721 vport->portNo = OvsGetVportNo(switchContext, vport->nicIndex,
722 vport->ovsType, vport->portType == NdisSwitchPortTypeExternal);
723 if (vport->portNo == 0) {
724 return NDIS_STATUS_RESOURCES;
726 ASSERT(OVS_IS_VPORT_ENTRY_NULL(switchContext,
727 OVS_VPORT_INDEX(vport->portNo)));
729 switchContext->vportArray[OVS_VPORT_INDEX(vport->portNo)] = vport;
731 switch (vport->portType) {
732 case NdisSwitchPortTypeExternal:
733 if (vport->nicIndex == 0) {
734 switchContext->externalPortId = vport->portId;
735 switchContext->externalVport = vport;
736 RtlStringCbPrintfA(vport->ovsName, OVS_MAX_PORT_NAME_LENGTH - 1,
737 "external.virtualAdapter");
740 switchContext->numPhysicalNics++;
741 RtlStringCbPrintfA(vport->ovsName, OVS_MAX_PORT_NAME_LENGTH - 1,
742 "external.%lu", (UINT32)vport->nicIndex);
745 case NdisSwitchPortTypeInternal:
746 switchContext->internalPortId = vport->portId;
747 switchContext->internalVport = vport;
748 RtlStringCbPrintfA(vport->ovsName, OVS_MAX_PORT_NAME_LENGTH - 1,
751 case NdisSwitchPortTypeSynthetic:
752 RtlStringCbPrintfA(vport->ovsName, OVS_MAX_PORT_NAME_LENGTH - 1,
753 "vmNICSyn.%lx", vport->portNo);
755 case NdisSwitchPortTypeEmulated:
756 RtlStringCbPrintfA(vport->ovsName, OVS_MAX_PORT_NAME_LENGTH - 1,
757 "vmNICEmu.%lx", vport->portNo);
760 StringCbLengthA(vport->ovsName, OVS_MAX_PORT_NAME_LENGTH - 1, &len);
761 vport->ovsNameLen = (UINT32)len;
762 if (vport->portType == NdisSwitchPortTypeExternal &&
763 vport->nicIndex == 0) {
764 return NDIS_STATUS_SUCCESS;
766 hash = OvsJhashBytes(vport->ovsName, vport->ovsNameLen, OVS_HASH_BASIS);
767 InsertHeadList(&switchContext->nameHashArray[hash & OVS_VPORT_MASK],
769 hash = OvsJhashWords(&vport->portId, 1, OVS_HASH_BASIS);
770 InsertHeadList(&switchContext->portHashArray[hash & OVS_VPORT_MASK],
772 switchContext->numVports++;
773 return NDIS_STATUS_SUCCESS;
778 OvsRemoveAndDeleteVport(POVS_SWITCH_CONTEXT switchContext,
779 POVS_VPORT_ENTRY vport)
781 UINT64 gen = vport->portNo >> 24;
783 if (vport->isExternal) {
784 if (vport->nicIndex == 0) {
785 ASSERT(switchContext->numPhysicalNics == 0);
786 switchContext->externalPortId = 0;
787 switchContext->externalVport = NULL;
788 OvsFreeMemory(vport);
791 ASSERT(switchContext->numPhysicalNics);
792 switchContext->numPhysicalNics--;
796 switch (vport->ovsType) {
797 case OVS_VPORT_TYPE_INTERNAL:
798 switchContext->internalPortId = 0;
799 switchContext->internalVport = NULL;
800 OvsInternalAdapterDown();
802 case OVS_VPORT_TYPE_VXLAN:
803 OvsCleanupVxlanTunnel(vport);
805 case OVS_VPORT_TYPE_GRE:
806 case OVS_VPORT_TYPE_GRE64:
808 case OVS_VPORT_TYPE_NETDEV:
813 RemoveEntryList(&vport->nameLink);
814 RemoveEntryList(&vport->portLink);
815 gen = (gen + 1) & 0xff;
816 switchContext->vportArray[OVS_VPORT_INDEX(vport->portNo)] =
818 switchContext->numVports--;
819 OvsFreeMemory(vport);
824 OvsAddConfiguredSwitchPorts(POVS_SWITCH_CONTEXT switchContext)
826 NDIS_STATUS status = NDIS_STATUS_SUCCESS;
828 PNDIS_SWITCH_PORT_PARAMETERS portParam;
829 PNDIS_SWITCH_PORT_ARRAY portArray = NULL;
830 POVS_VPORT_ENTRY vport;
832 OVS_LOG_TRACE("Enter: switchContext:%p", switchContext);
834 status = OvsGetPortsOnSwitch(switchContext, &portArray);
835 if (status != NDIS_STATUS_SUCCESS) {
839 for (arrIndex = 0; arrIndex < portArray->NumElements; arrIndex++) {
840 portParam = NDIS_SWITCH_PORT_AT_ARRAY_INDEX(portArray, arrIndex);
841 vport = (POVS_VPORT_ENTRY)OvsAllocateVport();
843 status = NDIS_STATUS_RESOURCES;
846 OvsInitVportWithPortParam(vport, portParam);
847 status = OvsInitVportCommon(switchContext, vport);
848 if (status != NDIS_STATUS_SUCCESS) {
849 OvsFreeMemory(vport);
854 if (status != NDIS_STATUS_SUCCESS) {
855 OvsClearAllSwitchVports(switchContext);
858 if (portArray != NULL) {
859 OvsFreeMemory(portArray);
861 OVS_LOG_TRACE("Exit: status: %x", status);
867 OvsInitConfiguredSwitchNics(POVS_SWITCH_CONTEXT switchContext)
869 NDIS_STATUS status = NDIS_STATUS_SUCCESS;
870 PNDIS_SWITCH_NIC_ARRAY nicArray = NULL;
872 PNDIS_SWITCH_NIC_PARAMETERS nicParam;
873 POVS_VPORT_ENTRY vport;
875 OVS_LOG_TRACE("Enter: switchContext: %p", switchContext);
879 status = OvsGetNicsOnSwitch(switchContext, &nicArray);
880 if (status != NDIS_STATUS_SUCCESS) {
883 for (arrIndex = 0; arrIndex < nicArray->NumElements; ++arrIndex) {
885 nicParam = NDIS_SWITCH_NIC_AT_ARRAY_INDEX(nicArray, arrIndex);
888 * XXX: Check if the port is configured with a VLAN. Disallow such a
889 * configuration, since we don't support tag-in-tag.
893 * XXX: Check if the port is connected to a VF. Disconnect the VF in
897 if (nicParam->NicType == NdisSwitchNicTypeExternal &&
898 nicParam->NicIndex != 0) {
899 POVS_VPORT_ENTRY virtVport =
900 (POVS_VPORT_ENTRY)switchContext->externalVport;
901 vport = OvsAllocateVport();
903 OvsInitPhysNicVport(vport, virtVport, nicParam->NicIndex);
904 status = OvsInitVportCommon(switchContext, vport);
905 if (status != NDIS_STATUS_SUCCESS) {
906 OvsFreeMemory(vport);
911 vport = OvsFindVportByPortIdAndNicIndex(switchContext,
916 OVS_LOG_ERROR("Fail to allocate vport");
919 OvsInitVportWithNicParam(switchContext, vport, nicParam);
920 if (nicParam->NicType == NdisSwitchNicTypeInternal) {
921 OvsInternalAdapterUp(vport->portNo, &nicParam->NetCfgInstanceId);
926 if (nicArray != NULL) {
927 OvsFreeMemory(nicArray);
929 OVS_LOG_TRACE("Exit: status: %x", status);
934 OvsClearAllSwitchVports(POVS_SWITCH_CONTEXT switchContext)
938 for (i = 0; i < OVS_MAX_VPORT_ARRAY_SIZE; i++) {
939 if (!OVS_IS_VPORT_ENTRY_NULL(switchContext, i)) {
940 OvsRemoveAndDeleteVport(switchContext,
941 (POVS_VPORT_ENTRY)switchContext->vportArray[i]);
944 if (switchContext->externalVport) {
945 OvsRemoveAndDeleteVport(switchContext,
946 (POVS_VPORT_ENTRY)switchContext->externalVport);
951 OvsDumpVportIoctl(PVOID inputBuffer,
957 UINT32 numVports, count;
960 POVS_VPORT_ENTRY vport;
961 LOCK_STATE_EX lockState;
963 if (inputLength < sizeof (UINT32)) {
964 return STATUS_INVALID_PARAMETER;
966 dpNo = *(UINT32 *)inputBuffer;
968 NdisAcquireSpinLock(gOvsCtrlLock);
969 if (gOvsSwitchContext == NULL ||
970 gOvsSwitchContext->dpNo != dpNo) {
971 NdisReleaseSpinLock(gOvsCtrlLock);
972 return STATUS_INVALID_PARAMETER;
975 * We should hold SwitchContext RW lock
978 NdisAcquireRWLockRead(gOvsSwitchContext->dispatchLock, &lockState,
979 NDIS_RWL_AT_DISPATCH_LEVEL);
980 numVports = outputLength/sizeof (UINT32);
981 numVports = MIN(gOvsSwitchContext->numVports, numVports);
982 outPtr = (UINT32 *)outputBuffer;
983 for (i = 0, count = 0;
984 i < OVS_MAX_VPORT_ARRAY_SIZE && count < numVports; i++) {
985 vport = (POVS_VPORT_ENTRY)gOvsSwitchContext->vportArray[i];
986 if (OVS_IS_VPORT_ENTRY_NULL(gOvsSwitchContext, i)) {
989 if (vport->ovsState == OVS_STATE_CONNECTED ||
990 vport->ovsState == OVS_STATE_NIC_CREATED) {
991 *outPtr = vport->portNo;
996 NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState);
997 NdisReleaseSpinLock(gOvsCtrlLock);
998 *replyLen = count * sizeof (UINT32);
999 return STATUS_SUCCESS;
1004 OvsGetVportIoctl(PVOID inputBuffer,
1007 UINT32 outputLength,
1012 POVS_VPORT_INFO info;
1013 POVS_VPORT_ENTRY vport;
1015 LOCK_STATE_EX lockState;
1017 if (inputLength < sizeof (OVS_VPORT_GET) ||
1018 outputLength < sizeof (OVS_VPORT_INFO)) {
1019 return STATUS_INVALID_PARAMETER;
1021 get = (POVS_VPORT_GET)inputBuffer;
1023 info = (POVS_VPORT_INFO)outputBuffer;
1024 RtlZeroMemory(info, sizeof (POVS_VPORT_INFO));
1026 NdisAcquireSpinLock(gOvsCtrlLock);
1027 if (gOvsSwitchContext == NULL ||
1028 gOvsSwitchContext->dpNo != dpNo) {
1029 NdisReleaseSpinLock(gOvsCtrlLock);
1030 return STATUS_INVALID_PARAMETER;
1033 NdisAcquireRWLockRead(gOvsSwitchContext->dispatchLock, &lockState,
1034 NDIS_RWL_AT_DISPATCH_LEVEL);
1035 if (get->portNo == 0) {
1036 StringCbLengthA(get->name, OVS_MAX_PORT_NAME_LENGTH - 1, &len);
1037 vport = OvsFindVportByOvsName(gOvsSwitchContext, get->name, (UINT32)len);
1039 vport = OvsFindVportByPortNo(gOvsSwitchContext, get->portNo);
1041 if (vport == NULL || (vport->ovsState != OVS_STATE_CONNECTED &&
1042 vport->ovsState != OVS_STATE_NIC_CREATED)) {
1043 NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState);
1044 NdisReleaseSpinLock(gOvsCtrlLock);
1046 * XXX Change to NO DEVICE
1048 return STATUS_DEVICE_DOES_NOT_EXIST;
1051 info->portNo = vport->portNo;
1052 info->type = vport->ovsType;
1053 RtlCopyMemory(info->macAddress, vport->permMacAddress,
1054 sizeof (vport->permMacAddress));
1055 RtlCopyMemory(info->name, vport->ovsName, vport->ovsNameLen + 1);
1057 info->rxPackets = vport->stats.rxPackets;
1058 info->rxBytes = vport->stats.rxBytes;
1059 info->txPackets = vport->stats.txPackets;
1060 info->txBytes = vport->stats.txBytes;
1061 info->rxErrors = vport->errStats.rxErrors;
1062 info->txErrors = vport->errStats.txErrors;
1063 info->rxDropped = vport->errStats.rxDropped;
1064 info->txDropped = vport->errStats.txDropped;
1066 NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState);
1067 NdisReleaseSpinLock(gOvsCtrlLock);
1068 *replyLen = sizeof (OVS_VPORT_INFO);
1069 return STATUS_SUCCESS;
1074 OvsInitTunnelVport(POVS_VPORT_ENTRY vport,
1075 POVS_VPORT_ADD_REQUEST addReq)
1078 NTSTATUS status = STATUS_SUCCESS;
1080 vport->isValidationPort = FALSE;
1081 vport->ovsType = addReq->type;
1082 vport->ovsState = OVS_STATE_PORT_CREATED;
1083 RtlCopyMemory(vport->ovsName, addReq->name, OVS_MAX_PORT_NAME_LENGTH);
1084 vport->ovsName[OVS_MAX_PORT_NAME_LENGTH - 1] = 0;
1085 StringCbLengthA(vport->ovsName, OVS_MAX_PORT_NAME_LENGTH - 1, &len);
1086 vport->ovsNameLen = (UINT32)len;
1087 switch (addReq->type) {
1088 case OVS_VPORT_TYPE_GRE:
1090 case OVS_VPORT_TYPE_GRE64:
1092 case OVS_VPORT_TYPE_VXLAN:
1093 status = OvsInitVxlanTunnel(vport, addReq);
1102 OvsAddVportIoctl(PVOID inputBuffer,
1105 UINT32 outputLength,
1108 NTSTATUS status = STATUS_SUCCESS;
1109 POVS_VPORT_INFO vportInfo;
1110 POVS_VPORT_ADD_REQUEST addReq;
1111 POVS_VPORT_ENTRY vport;
1112 LOCK_STATE_EX lockState;
1116 OVS_LOG_TRACE("Enter: inputLength: %u, outputLength: %u",
1117 inputLength, outputLength);
1118 if (inputLength < sizeof (OVS_VPORT_ADD_REQUEST) ||
1119 outputLength < sizeof (OVS_VPORT_INFO)) {
1120 status = STATUS_INVALID_PARAMETER;
1121 goto vport_add_done;
1123 addReq = (POVS_VPORT_ADD_REQUEST)inputBuffer;
1124 addReq->name[OVS_MAX_PORT_NAME_LENGTH - 1] = 0;
1126 switch (addReq->type) {
1127 case OVS_VPORT_TYPE_GRE:
1128 index = OVS_GRE_VPORT_INDEX;
1130 case OVS_VPORT_TYPE_GRE64:
1131 index = OVS_GRE64_VPORT_INDEX;
1133 case OVS_VPORT_TYPE_VXLAN:
1134 index = OVS_VXLAN_VPORT_INDEX;
1137 status = STATUS_NOT_SUPPORTED;
1138 goto vport_add_done;
1141 vport = (POVS_VPORT_ENTRY)OvsAllocateVport();
1142 if (vport == NULL) {
1143 status = STATUS_INSUFFICIENT_RESOURCES;
1144 goto vport_add_done;
1147 NdisAcquireSpinLock(gOvsCtrlLock);
1148 if (gOvsSwitchContext == NULL ||
1149 gOvsSwitchContext->dpNo != addReq->dpNo) {
1150 NdisReleaseSpinLock(gOvsCtrlLock);
1151 status = STATUS_INVALID_PARAMETER;
1152 OvsFreeMemory(vport);
1153 goto vport_add_done;
1155 NdisAcquireRWLockRead(gOvsSwitchContext->dispatchLock, &lockState,
1156 NDIS_RWL_AT_DISPATCH_LEVEL);
1157 if (!OVS_IS_VPORT_ENTRY_NULL(gOvsSwitchContext, index)) {
1158 status = STATUS_DEVICE_BUSY;
1159 NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState);
1160 NdisReleaseSpinLock(gOvsCtrlLock);
1161 OvsFreeMemory(vport);
1162 goto vport_add_done;
1165 status = OvsInitTunnelVport(vport, addReq);
1166 if (status != STATUS_SUCCESS) {
1167 NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState);
1168 NdisReleaseSpinLock(gOvsCtrlLock);
1169 OvsFreeMemory(vport);
1170 goto vport_add_done;
1173 status = OvsInitVportCommon(gOvsSwitchContext, vport);
1174 ASSERT(status == NDIS_STATUS_SUCCESS);
1176 vport->ovsState = OVS_STATE_CONNECTED;
1177 vport->nicState = NdisSwitchNicStateConnected;
1179 vportInfo = (POVS_VPORT_INFO)outputBuffer;
1181 RtlZeroMemory(vportInfo, sizeof (POVS_VPORT_INFO));
1182 vportInfo->dpNo = gOvsSwitchContext->dpNo;
1183 vportInfo->portNo = vport->portNo;
1184 vportInfo->type = vport->ovsType;
1185 RtlCopyMemory(vportInfo->name, vport->ovsName, vport->ovsNameLen + 1);
1186 portNo = vport->portNo;
1188 NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState);
1189 NdisReleaseSpinLock(gOvsCtrlLock);
1190 OvsPostEvent(portNo, OVS_EVENT_CONNECT | OVS_EVENT_LINK_UP);
1191 *replyLen = sizeof (OVS_VPORT_INFO);
1192 status = STATUS_SUCCESS;
1194 OVS_LOG_TRACE("Exit: byteReturned: %u, status: %x",
1200 OvsDelVportIoctl(PVOID inputBuffer,
1204 NTSTATUS status = STATUS_SUCCESS;
1205 POVS_VPORT_DELETE_REQUEST delReq;
1206 LOCK_STATE_EX lockState;
1207 POVS_VPORT_ENTRY vport;
1211 OVS_LOG_TRACE("Enter: inputLength: %u", inputLength);
1213 if (inputLength < sizeof (OVS_VPORT_DELETE_REQUEST)) {
1214 status = STATUS_INVALID_PARAMETER;
1215 goto vport_del_done;
1217 delReq = (POVS_VPORT_DELETE_REQUEST)inputBuffer;
1219 NdisAcquireSpinLock(gOvsCtrlLock);
1220 if (gOvsSwitchContext == NULL ||
1221 gOvsSwitchContext->dpNo != delReq->dpNo) {
1222 NdisReleaseSpinLock(gOvsCtrlLock);
1223 status = STATUS_INVALID_PARAMETER;
1224 goto vport_del_done;
1226 NdisAcquireRWLockRead(gOvsSwitchContext->dispatchLock, &lockState,
1227 NDIS_RWL_AT_DISPATCH_LEVEL);
1228 if (delReq->portNo == 0) {
1229 StringCbLengthA(delReq->name, OVS_MAX_PORT_NAME_LENGTH - 1, &len);
1230 vport = OvsFindVportByOvsName(gOvsSwitchContext, delReq->name,
1233 vport = OvsFindVportByPortNo(gOvsSwitchContext, delReq->portNo);
1236 OVS_LOG_INFO("delete vport: %s, portNo: %x", vport->ovsName,
1238 portNo = vport->portNo;
1239 OvsRemoveAndDeleteVport(gOvsSwitchContext, vport);
1241 status = STATUS_DEVICE_DOES_NOT_EXIST;
1243 NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState);
1244 NdisReleaseSpinLock(gOvsCtrlLock);
1246 OvsPostEvent(portNo, OVS_EVENT_DISCONNECT | OVS_EVENT_LINK_DOWN);
1249 OVS_LOG_TRACE("Exit: byteReturned: %u, status: %x",
1255 OvsConvertIfCountedStrToAnsiStr(PIF_COUNTED_STRING wStr,
1260 UNICODE_STRING ustr;
1264 ustr.Buffer = wStr->String;
1265 ustr.Length = wStr->Length;
1266 ustr.MaximumLength = IF_MAX_STRING_SIZE;
1269 astr.MaximumLength = maxStrLen;
1272 size = RtlUnicodeStringToAnsiSize(&ustr);
1273 if (size > maxStrLen) {
1274 return STATUS_BUFFER_OVERFLOW;
1277 status = RtlUnicodeStringToAnsiString(&astr, &ustr, FALSE);
1279 ASSERT(status == STATUS_SUCCESS);
1280 if (status != STATUS_SUCCESS) {
1283 ASSERT(astr.Length <= maxStrLen);
1284 str[astr.Length] = 0;
1285 return STATUS_SUCCESS;
1290 * XXX: Get rid of USE_NEW_VPORT_ADD_WORKFLOW while checking in the code for
1291 * new vport add workflow, or set USE_NEW_VPORT_ADD_WORKFLOW to 1.
1293 #define USE_NEW_VPORT_ADD_WORKFLOW 0
1295 OvsGetExtInfoIoctl(POVS_VPORT_GET vportGet,
1296 POVS_VPORT_EXT_INFO extInfo)
1298 POVS_VPORT_ENTRY vport;
1300 LOCK_STATE_EX lockState;
1301 NTSTATUS status = STATUS_SUCCESS;
1302 BOOLEAN doConvert = FALSE;
1304 RtlZeroMemory(extInfo, sizeof (POVS_VPORT_EXT_INFO));
1305 NdisAcquireRWLockRead(gOvsSwitchContext->dispatchLock, &lockState,
1306 NDIS_RWL_AT_DISPATCH_LEVEL);
1307 if (vportGet->portNo == 0) {
1308 StringCbLengthA(vportGet->name, OVS_MAX_PORT_NAME_LENGTH - 1, &len);
1309 #if USE_NEW_VPORT_ADD_WORKFLOW == 0
1310 vport = OvsFindVportByOvsName(gOvsSwitchContext, vportGet->name,
1313 vport = OvsFindVportByHvName(gOvsSwitchContext, vportGet->name);
1316 vport = OvsFindVportByPortNo(gOvsSwitchContext, vportGet->portNo);
1318 if (vport == NULL || (vport->ovsState != OVS_STATE_CONNECTED &&
1319 vport->ovsState != OVS_STATE_NIC_CREATED)) {
1320 NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState);
1321 NdisReleaseSpinLock(gOvsCtrlLock);
1322 if (vportGet->portNo) {
1323 OVS_LOG_WARN("vport %u does not exist any more", vportGet->portNo);
1325 OVS_LOG_WARN("vport %s does not exist any more", vportGet->name);
1327 status = STATUS_DEVICE_DOES_NOT_EXIST;
1330 extInfo->dpNo = vportGet->dpNo;
1331 extInfo->portNo = vport->portNo;
1332 RtlCopyMemory(extInfo->macAddress, vport->currMacAddress,
1333 sizeof (vport->currMacAddress));
1334 RtlCopyMemory(extInfo->permMACAddress, vport->permMacAddress,
1335 sizeof (vport->permMacAddress));
1336 if (vport->ovsType == OVS_VPORT_TYPE_NETDEV) {
1337 RtlCopyMemory(extInfo->vmMACAddress, vport->vmMacAddress,
1338 sizeof (vport->vmMacAddress));
1340 extInfo->nicIndex = vport->nicIndex;
1341 extInfo->portId = vport->portId;
1342 extInfo->type = vport->ovsType;
1343 extInfo->mtu = vport->mtu;
1347 if (vport->ovsState == OVS_STATE_NIC_CREATED) {
1348 extInfo->status = OVS_EVENT_CONNECT | OVS_EVENT_LINK_DOWN;
1349 } else if (vport->ovsState == OVS_STATE_CONNECTED) {
1350 extInfo->status = OVS_EVENT_CONNECT | OVS_EVENT_LINK_UP;
1352 extInfo->status = OVS_EVENT_DISCONNECT;
1354 if (extInfo->type == OVS_VPORT_TYPE_NETDEV &&
1355 (vport->ovsState == OVS_STATE_NIC_CREATED ||
1356 vport->ovsState == OVS_STATE_CONNECTED)) {
1359 extInfo->vmUUID[0] = 0;
1360 extInfo->vifUUID[0] = 0;
1362 #if USE_NEW_VPORT_ADD_WORKFLOW == 0
1363 RtlCopyMemory(extInfo->name, vport->ovsName, vport->ovsNameLen + 1);
1365 NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState);
1366 NdisReleaseSpinLock(gOvsCtrlLock);
1368 #if USE_NEW_VPORT_ADD_WORKFLOW == 1
1369 status = OvsConvertIfCountedStrToAnsiStr(&vport->portFriendlyName,
1371 OVS_MAX_PORT_NAME_LENGTH);
1372 if (status != STATUS_SUCCESS) {
1373 OVS_LOG_INFO("Fail to convert NIC name.");
1374 extInfo->vmUUID[0] = 0;
1378 status = OvsConvertIfCountedStrToAnsiStr(&vport->vmName,
1380 OVS_MAX_VM_UUID_LEN);
1381 if (status != STATUS_SUCCESS) {
1382 OVS_LOG_INFO("Fail to convert VM name.");
1383 extInfo->vmUUID[0] = 0;
1386 status = OvsConvertIfCountedStrToAnsiStr(&vport->nicName,
1388 OVS_MAX_VIF_UUID_LEN);
1389 if (status != STATUS_SUCCESS) {
1390 OVS_LOG_INFO("Fail to convert nic UUID");
1391 extInfo->vifUUID[0] = 0;
1394 * for now ignore status
1396 status = STATUS_SUCCESS;
1404 * --------------------------------------------------------------------------
1405 * Command Handler for 'OVS_WIN_NETDEV_CMD_GET'.
1406 * --------------------------------------------------------------------------
1409 OvsGetNetdevCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx,
1412 NTSTATUS status = STATUS_SUCCESS;
1413 POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer;
1414 POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer;
1415 NL_ERROR nlError = NL_ERROR_SUCCESS;
1416 OVS_VPORT_GET vportGet;
1417 OVS_VPORT_EXT_INFO info;
1418 LOCK_STATE_EX lockState;
1420 static const NL_POLICY ovsNetdevPolicy[] = {
1421 [OVS_WIN_NETDEV_ATTR_NAME] = { .type = NL_A_STRING,
1423 .maxLen = IFNAMSIZ },
1425 PNL_ATTR netdevAttrs[ARRAY_SIZE(ovsNetdevPolicy)];
1427 /* input buffer has been validated while validating transaction dev op. */
1428 ASSERT(usrParamsCtx->inputBuffer != NULL &&
1429 usrParamsCtx->inputLength > sizeof *msgIn);
1431 if (msgOut == NULL || usrParamsCtx->outputLength < sizeof *msgOut) {
1432 return STATUS_INVALID_BUFFER_SIZE;
1435 if (!NlAttrParse((PNL_MSG_HDR)msgIn,
1436 NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN,
1437 NlMsgAttrsLen((PNL_MSG_HDR)msgIn),
1438 ovsNetdevPolicy, netdevAttrs, ARRAY_SIZE(netdevAttrs))) {
1439 return STATUS_INVALID_PARAMETER;
1442 OvsAcquireCtrlLock();
1443 if (!gOvsSwitchContext) {
1444 OvsReleaseCtrlLock();
1445 return STATUS_INVALID_PARAMETER;
1448 vportGet.portNo = 0;
1449 RtlCopyMemory(&vportGet.name, NlAttrGet(netdevAttrs[OVS_VPORT_ATTR_NAME]),
1450 NlAttrGetSize(netdevAttrs[OVS_VPORT_ATTR_NAME]));
1452 NdisAcquireRWLockRead(gOvsSwitchContext->dispatchLock, &lockState, 0);
1453 status = OvsGetExtInfoIoctl(&vportGet, &info);
1454 if (status == STATUS_DEVICE_DOES_NOT_EXIST) {
1455 nlError = NL_ERROR_NODEV;
1456 NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState);
1457 OvsReleaseCtrlLock();
1460 NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState);
1462 status = CreateNetlinkMesgForNetdev(&info, msgIn,
1463 usrParamsCtx->outputBuffer, usrParamsCtx->outputLength,
1464 gOvsSwitchContext->dpNo);
1465 if (status == STATUS_SUCCESS) {
1466 *replyLen = msgOut->nlMsg.nlmsgLen;
1468 OvsReleaseCtrlLock();
1471 if (nlError != NL_ERROR_SUCCESS) {
1472 POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)
1473 usrParamsCtx->outputBuffer;
1475 BuildErrorMsg(msgIn, msgError, nlError);
1476 *replyLen = msgError->nlMsg.nlmsgLen;
1479 return STATUS_SUCCESS;
1484 * --------------------------------------------------------------------------
1485 * Utility function to construct an OVS_MESSAGE for the specified vport. The
1486 * OVS_MESSAGE contains the output of a netdev command.
1487 * --------------------------------------------------------------------------
1490 CreateNetlinkMesgForNetdev(POVS_VPORT_EXT_INFO info,
1500 UINT32 netdevFlags = 0;
1502 NlBufInit(&nlBuffer, outBuffer, outBufLen);
1504 BuildReplyMsgFromMsgIn(msgIn, &msgOut, 0);
1505 msgOut.ovsHdr.dp_ifindex = dpIfIndex;
1507 ok = NlMsgPutHead(&nlBuffer, (PCHAR)&msgOut, sizeof msgOut);
1509 return STATUS_INSUFFICIENT_RESOURCES;
1512 ok = NlMsgPutTailU32(&nlBuffer, OVS_WIN_NETDEV_ATTR_PORT_NO,
1515 return STATUS_INSUFFICIENT_RESOURCES;
1518 ok = NlMsgPutTailU32(&nlBuffer, OVS_WIN_NETDEV_ATTR_TYPE, info->type);
1520 return STATUS_INSUFFICIENT_RESOURCES;
1523 ok = NlMsgPutTailString(&nlBuffer, OVS_WIN_NETDEV_ATTR_NAME,
1526 return STATUS_INSUFFICIENT_RESOURCES;
1529 ok = NlMsgPutTailUnspec(&nlBuffer, OVS_WIN_NETDEV_ATTR_MAC_ADDR,
1530 (PCHAR)info->macAddress, sizeof (info->macAddress));
1532 return STATUS_INSUFFICIENT_RESOURCES;
1535 ok = NlMsgPutTailU32(&nlBuffer, OVS_WIN_NETDEV_ATTR_MTU, info->mtu);
1537 return STATUS_INSUFFICIENT_RESOURCES;
1540 if (info->status != OVS_EVENT_CONNECT) {
1541 netdevFlags = OVS_WIN_NETDEV_IFF_UP;
1543 ok = NlMsgPutTailU32(&nlBuffer, OVS_WIN_NETDEV_ATTR_IF_FLAGS,
1546 return STATUS_INSUFFICIENT_RESOURCES;
1550 * XXX: add netdev_stats when we have the definition available in the
1554 nlMsg = (PNL_MSG_HDR)NlBufAt(&nlBuffer, 0, 0);
1555 nlMsg->nlmsgLen = NlBufSize(&nlBuffer);
1557 return STATUS_SUCCESS;
1560 static __inline VOID
1561 OvsWaitActivate(POVS_SWITCH_CONTEXT switchContext, ULONG sleepMicroSec)
1563 while ((!switchContext->isActivated) &&
1564 (!switchContext->isActivateFailed)) {
1565 /* Wait for the switch to be active and
1566 * the list of ports in OVS to be initialized. */
1567 NdisMSleep(sleepMicroSec);