]> git.proxmox.com Git - ovs.git/blame - datapath-windows/ovsext/Switch.c
datapath-windows: Removed duplicate instance pid removal
[ovs.git] / datapath-windows / ovsext / Switch.c
CommitLineData
c803536e
SS
1/*
2 * Copyright (c) 2014 VMware, Inc.
3 *
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:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17/*
18 * This file contains the implementation of the management functionality of the
19 * OVS.
20 */
21
22#include "precomp.h"
23
fa1324c9
SG
24#include "Switch.h"
25#include "Vport.h"
26#include "Event.h"
27#include "Flow.h"
28#include "IpHelper.h"
fa1324c9 29#include "Oid.h"
c803536e
SS
30
31#ifdef OVS_DBG_MOD
32#undef OVS_DBG_MOD
33#endif
34#define OVS_DBG_MOD OVS_DBG_SWITCH
fa1324c9 35#include "Debug.h"
c803536e
SS
36
37POVS_SWITCH_CONTEXT gOvsSwitchContext;
3ed424e5 38LONG volatile gOvsInAttach;
4f3988e0
NR
39UINT64 ovsTimeIncrementPerTick;
40
c803536e
SS
41extern NDIS_HANDLE gOvsExtDriverHandle;
42extern NDIS_HANDLE gOvsExtDriverObject;
43
6c4e7adb
SV
44/*
45 * Reference count used to prevent premature deallocation of the global switch
46 * context structure, gOvsSwitchContext.
47 */
48volatile LONG gOvsSwitchContextRefCount = 1;
49
c803536e
SS
50static NDIS_STATUS OvsCreateSwitch(NDIS_HANDLE ndisFilterHandle,
51 POVS_SWITCH_CONTEXT *switchContextOut);
52static NDIS_STATUS OvsInitSwitchContext(POVS_SWITCH_CONTEXT switchContext);
53static VOID OvsDeleteSwitch(POVS_SWITCH_CONTEXT switchContext);
3a6de110 54static VOID OvsUninitSwitchContext(POVS_SWITCH_CONTEXT switchContext);
c803536e
SS
55static NDIS_STATUS OvsActivateSwitch(POVS_SWITCH_CONTEXT switchContext);
56
57
58/*
59 * --------------------------------------------------------------------------
60 * Implements filter driver's FilterAttach function.
61 *
62 * This function allocates the switch context, and initializes its necessary
63 * members.
64 * --------------------------------------------------------------------------
65 */
66NDIS_STATUS
67OvsExtAttach(NDIS_HANDLE ndisFilterHandle,
68 NDIS_HANDLE filterDriverContext,
69 PNDIS_FILTER_ATTACH_PARAMETERS attachParameters)
70{
71 NDIS_STATUS status = NDIS_STATUS_FAILURE;
72 NDIS_FILTER_ATTRIBUTES ovsExtAttributes;
73 POVS_SWITCH_CONTEXT switchContext = NULL;
74
75 UNREFERENCED_PARAMETER(filterDriverContext);
76
77 OVS_LOG_TRACE("Enter: ndisFilterHandle %p", ndisFilterHandle);
78
79 ASSERT(filterDriverContext == (NDIS_HANDLE)gOvsExtDriverObject);
80 if (attachParameters->MiniportMediaType != NdisMedium802_3) {
81 status = NDIS_STATUS_INVALID_PARAMETER;
82 goto cleanup;
83 }
84
85 if (gOvsExtDriverHandle == NULL) {
86 OVS_LOG_TRACE("Exit: OVSEXT driver is not loaded.");
87 ASSERT(FALSE);
88 goto cleanup;
89 }
90
c803536e 91 if (gOvsSwitchContext) {
c803536e
SS
92 OVS_LOG_TRACE("Exit: Failed to create OVS Switch, only one datapath is"
93 "supported, %p.", gOvsSwitchContext);
94 goto cleanup;
95 }
3ed424e5
SV
96
97 if (InterlockedCompareExchange(&gOvsInAttach, 1, 0)) {
c803536e
SS
98 /* Just fail the request. */
99 OVS_LOG_TRACE("Exit: Failed to create OVS Switch, since another attach"
100 "instance is in attach process.");
101 goto cleanup;
102 }
c803536e
SS
103
104 status = OvsInitIpHelper(ndisFilterHandle);
105 if (status != STATUS_SUCCESS) {
106 OVS_LOG_ERROR("Exit: Failed to initialize IP helper.");
107 goto cleanup;
108 }
109
110 status = OvsCreateSwitch(ndisFilterHandle, &switchContext);
111 if (status != NDIS_STATUS_SUCCESS) {
112 OvsCleanupIpHelper();
113 goto cleanup;
114 }
115 ASSERT(switchContext);
116
117 /*
118 * Register the switch context with NDIS so NDIS can pass it back to the
3ed424e5 119 * FilterXXX callback functions as the 'FilterModuleContext' parameter.
c803536e
SS
120 */
121 RtlZeroMemory(&ovsExtAttributes, sizeof(NDIS_FILTER_ATTRIBUTES));
122 ovsExtAttributes.Header.Revision = NDIS_FILTER_ATTRIBUTES_REVISION_1;
123 ovsExtAttributes.Header.Size = sizeof(NDIS_FILTER_ATTRIBUTES);
124 ovsExtAttributes.Header.Type = NDIS_OBJECT_TYPE_FILTER_ATTRIBUTES;
125 ovsExtAttributes.Flags = 0;
126
127 NDIS_DECLARE_FILTER_MODULE_CONTEXT(OVS_SWITCH_CONTEXT);
128 status = NdisFSetAttributes(ndisFilterHandle, switchContext, &ovsExtAttributes);
129 if (status != NDIS_STATUS_SUCCESS) {
130 OVS_LOG_ERROR("Failed to set attributes.");
131 OvsCleanupIpHelper();
132 goto cleanup;
133 }
134
135 /* Setup the state machine. */
136 switchContext->controlFlowState = OvsSwitchAttached;
137 switchContext->dataFlowState = OvsSwitchPaused;
138
139 gOvsSwitchContext = switchContext;
140 KeMemoryBarrier();
141
142cleanup:
143 gOvsInAttach = FALSE;
144 if (status != NDIS_STATUS_SUCCESS) {
145 if (switchContext != NULL) {
146 OvsDeleteSwitch(switchContext);
147 }
148 }
149 OVS_LOG_TRACE("Exit: status %x", status);
150
151 return status;
152}
153
154
155/*
156 * --------------------------------------------------------------------------
157 * This function allocated the switch context, and initializes its necessary
158 * members.
159 * --------------------------------------------------------------------------
160 */
161NDIS_STATUS
162OvsCreateSwitch(NDIS_HANDLE ndisFilterHandle,
163 POVS_SWITCH_CONTEXT *switchContextOut)
164{
165 NDIS_STATUS status;
166 POVS_SWITCH_CONTEXT switchContext;
167 NDIS_SWITCH_CONTEXT hostSwitchContext;
168 NDIS_SWITCH_OPTIONAL_HANDLERS hostSwitchHandler;
169
170 OVS_LOG_TRACE("Enter: Create switch object");
171
ba7f9d90
SV
172 switchContext = (POVS_SWITCH_CONTEXT) OvsAllocateMemoryWithTag(
173 sizeof(OVS_SWITCH_CONTEXT), OVS_SWITCH_POOL_TAG);
c803536e
SS
174 if (switchContext == NULL) {
175 status = NDIS_STATUS_RESOURCES;
176 goto create_switch_done;
177 }
178 RtlZeroMemory(switchContext, sizeof(OVS_SWITCH_CONTEXT));
179
180 /* Initialize the switch. */
181 hostSwitchHandler.Header.Type = NDIS_OBJECT_TYPE_SWITCH_OPTIONAL_HANDLERS;
182 hostSwitchHandler.Header.Size = NDIS_SIZEOF_SWITCH_OPTIONAL_HANDLERS_REVISION_1;
183 hostSwitchHandler.Header.Revision = NDIS_SWITCH_OPTIONAL_HANDLERS_REVISION_1;
184
185 status = NdisFGetOptionalSwitchHandlers(ndisFilterHandle,
186 &hostSwitchContext,
187 &hostSwitchHandler);
188 if (status != NDIS_STATUS_SUCCESS) {
189 OVS_LOG_ERROR("OvsExtAttach: Extension is running in "
190 "non-switch environment.");
ba7f9d90 191 OvsFreeMemoryWithTag(switchContext, OVS_SWITCH_POOL_TAG);
c803536e
SS
192 goto create_switch_done;
193 }
194
195 switchContext->NdisFilterHandle = ndisFilterHandle;
196 switchContext->NdisSwitchContext = hostSwitchContext;
197 RtlCopyMemory(&switchContext->NdisSwitchHandlers, &hostSwitchHandler,
198 sizeof(NDIS_SWITCH_OPTIONAL_HANDLERS));
199
200 status = OvsInitSwitchContext(switchContext);
201 if (status != NDIS_STATUS_SUCCESS) {
ba7f9d90 202 OvsFreeMemoryWithTag(switchContext, OVS_SWITCH_POOL_TAG);
c803536e
SS
203 goto create_switch_done;
204 }
205
206 status = OvsTunnelFilterInitialize(gOvsExtDriverObject);
207 if (status != NDIS_STATUS_SUCCESS) {
3a6de110 208 OvsUninitSwitchContext(switchContext);
c803536e
SS
209 goto create_switch_done;
210 }
211 *switchContextOut = switchContext;
212
213create_switch_done:
214 OVS_LOG_TRACE("Exit: switchContext: %p status: %#lx",
215 switchContext, status);
216 return status;
217}
218
219
220/*
221 * --------------------------------------------------------------------------
222 * Implements filter driver's FilterDetach function.
223 * --------------------------------------------------------------------------
224 */
225_Use_decl_annotations_
226VOID
227OvsExtDetach(NDIS_HANDLE filterModuleContext)
228{
229 POVS_SWITCH_CONTEXT switchContext = (POVS_SWITCH_CONTEXT)filterModuleContext;
230
231 OVS_LOG_TRACE("Enter: filterModuleContext %p", filterModuleContext);
232
233 ASSERT(switchContext->dataFlowState == OvsSwitchPaused);
234 switchContext->controlFlowState = OvsSwitchDetached;
235 KeMemoryBarrier();
236 while(switchContext->pendingOidCount > 0) {
237 NdisMSleep(1000);
238 }
239 OvsDeleteSwitch(switchContext);
240 OvsCleanupIpHelper();
241 gOvsSwitchContext = NULL;
242 /* This completes the cleanup, and a new attach can be handled now. */
243
244 OVS_LOG_TRACE("Exit: OvsDetach Successfully");
245}
246
247
248/*
249 * --------------------------------------------------------------------------
250 * This function deletes the switch by freeing all memory previously allocated.
251 * XXX need synchronization with other path.
252 * --------------------------------------------------------------------------
253 */
254VOID
255OvsDeleteSwitch(POVS_SWITCH_CONTEXT switchContext)
256{
3a6de110 257 UINT32 dpNo = (UINT32) -1;
c803536e
SS
258
259 OVS_LOG_TRACE("Enter: switchContext:%p", switchContext);
260
3a6de110
SV
261 if (switchContext)
262 {
263 dpNo = switchContext->dpNo;
264 OvsTunnelFilterUninitialize(gOvsExtDriverObject);
265 OvsClearAllSwitchVports(switchContext);
266 OvsUninitSwitchContext(switchContext);
3a6de110 267 }
c803536e
SS
268 OVS_LOG_TRACE("Exit: deleted switch %p dpNo: %d", switchContext, dpNo);
269}
270
271
272/*
273 * --------------------------------------------------------------------------
274 * Implements filter driver's FilterRestart function.
275 * --------------------------------------------------------------------------
276 */
277_Use_decl_annotations_
278NDIS_STATUS
279OvsExtRestart(NDIS_HANDLE filterModuleContext,
280 PNDIS_FILTER_RESTART_PARAMETERS filterRestartParameters)
281{
282 POVS_SWITCH_CONTEXT switchContext = (POVS_SWITCH_CONTEXT)filterModuleContext;
283 NDIS_STATUS status = NDIS_STATUS_SUCCESS;
284 BOOLEAN switchActive;
285
286 UNREFERENCED_PARAMETER(filterRestartParameters);
287
288 OVS_LOG_TRACE("Enter: filterModuleContext %p",
289 filterModuleContext);
290
291 /* Activate the switch if this is the first restart. */
292 if (!switchContext->isActivated && !switchContext->isActivateFailed) {
293 status = OvsQuerySwitchActivationComplete(switchContext,
294 &switchActive);
295 if (status != NDIS_STATUS_SUCCESS) {
296 switchContext->isActivateFailed = TRUE;
297 status = NDIS_STATUS_RESOURCES;
298 goto cleanup;
299 }
300
301 if (switchActive) {
302 status = OvsActivateSwitch(switchContext);
303
304 if (status != NDIS_STATUS_SUCCESS) {
305 OVS_LOG_WARN("Failed to activate switch, dpNo:%d",
306 switchContext->dpNo);
307 status = NDIS_STATUS_RESOURCES;
308 goto cleanup;
309 }
310 }
311 }
312
313 ASSERT(switchContext->dataFlowState == OvsSwitchPaused);
314 switchContext->dataFlowState = OvsSwitchRunning;
315
316cleanup:
317 OVS_LOG_TRACE("Exit: Restart switch:%p, dpNo: %d, status: %#x",
318 switchContext, switchContext->dpNo, status);
319 return status;
320}
321
322
323/*
324 * --------------------------------------------------------------------------
325 * Implements filter driver's FilterPause function
326 * --------------------------------------------------------------------------
327 */
328NDIS_STATUS
329OvsExtPause(NDIS_HANDLE filterModuleContext,
330 PNDIS_FILTER_PAUSE_PARAMETERS pauseParameters)
331{
332 POVS_SWITCH_CONTEXT switchContext = (POVS_SWITCH_CONTEXT)filterModuleContext;
333
334 UNREFERENCED_PARAMETER(pauseParameters);
335 OVS_LOG_TRACE("Enter: filterModuleContext %p",
336 filterModuleContext);
337
338 ASSERT(switchContext->dataFlowState == OvsSwitchRunning);
339 switchContext->dataFlowState = OvsSwitchPaused;
340 KeMemoryBarrier();
341 while(switchContext->pendingOidCount > 0) {
342 NdisMSleep(1000);
343 }
344
345 OVS_LOG_TRACE("Exit: OvsDetach Successfully");
346 return NDIS_STATUS_SUCCESS;
347}
348
349static NDIS_STATUS
350OvsInitSwitchContext(POVS_SWITCH_CONTEXT switchContext)
351{
352 int i;
353 NTSTATUS status;
354
355 OVS_LOG_TRACE("Enter: switchContext: %p", switchContext);
356
357 switchContext->dispatchLock =
358 NdisAllocateRWLock(switchContext->NdisFilterHandle);
359
ba7f9d90
SV
360 switchContext->portNoHashArray = (PLIST_ENTRY)OvsAllocateMemoryWithTag(
361 sizeof(LIST_ENTRY) * OVS_MAX_VPORT_ARRAY_SIZE, OVS_SWITCH_POOL_TAG);
362 switchContext->ovsPortNameHashArray = (PLIST_ENTRY)OvsAllocateMemoryWithTag(
363 sizeof(LIST_ENTRY) * OVS_MAX_VPORT_ARRAY_SIZE, OVS_SWITCH_POOL_TAG);
364 switchContext->portIdHashArray= (PLIST_ENTRY)OvsAllocateMemoryWithTag(
365 sizeof(LIST_ENTRY) * OVS_MAX_VPORT_ARRAY_SIZE, OVS_SWITCH_POOL_TAG);
366 switchContext->pidHashArray = (PLIST_ENTRY)OvsAllocateMemoryWithTag(
367 sizeof(LIST_ENTRY) * OVS_MAX_PID_ARRAY_SIZE, OVS_SWITCH_POOL_TAG);
c803536e
SS
368 status = OvsAllocateFlowTable(&switchContext->datapath, switchContext);
369
370 if (status == NDIS_STATUS_SUCCESS) {
371 status = OvsInitBufferPool(switchContext);
372 }
373 if (status != NDIS_STATUS_SUCCESS ||
374 switchContext->dispatchLock == NULL ||
429d4556 375 switchContext->portNoHashArray == NULL ||
147c91db 376 switchContext->ovsPortNameHashArray == NULL ||
75752ef5
AS
377 switchContext->portIdHashArray== NULL ||
378 switchContext->pidHashArray == NULL) {
c803536e
SS
379 if (switchContext->dispatchLock) {
380 NdisFreeRWLock(switchContext->dispatchLock);
381 }
429d4556 382 if (switchContext->portNoHashArray) {
ba7f9d90
SV
383 OvsFreeMemoryWithTag(switchContext->portNoHashArray,
384 OVS_SWITCH_POOL_TAG);
c803536e 385 }
147c91db 386 if (switchContext->ovsPortNameHashArray) {
ba7f9d90
SV
387 OvsFreeMemoryWithTag(switchContext->ovsPortNameHashArray,
388 OVS_SWITCH_POOL_TAG);
c803536e 389 }
91c261cd 390 if (switchContext->portIdHashArray) {
ba7f9d90
SV
391 OvsFreeMemoryWithTag(switchContext->portIdHashArray,
392 OVS_SWITCH_POOL_TAG);
c803536e 393 }
75752ef5 394 if (switchContext->pidHashArray) {
ba7f9d90
SV
395 OvsFreeMemoryWithTag(switchContext->pidHashArray,
396 OVS_SWITCH_POOL_TAG);
75752ef5
AS
397 }
398
c803536e
SS
399 OvsDeleteFlowTable(&switchContext->datapath);
400 OvsCleanupBufferPool(switchContext);
401
402 OVS_LOG_TRACE("Exit: Failed to init switchContext");
403 return NDIS_STATUS_RESOURCES;
404 }
405
406 for (i = 0; i < OVS_MAX_VPORT_ARRAY_SIZE; i++) {
147c91db 407 InitializeListHead(&switchContext->ovsPortNameHashArray[i]);
c803536e
SS
408 }
409 for (i = 0; i < OVS_MAX_VPORT_ARRAY_SIZE; i++) {
91c261cd 410 InitializeListHead(&switchContext->portIdHashArray[i]);
c803536e 411 }
429d4556
AS
412 for (i = 0; i < OVS_MAX_VPORT_ARRAY_SIZE; i++) {
413 InitializeListHead(&switchContext->portNoHashArray[i]);
414 }
c803536e 415
75752ef5
AS
416 for (i = 0; i < OVS_MAX_PID_ARRAY_SIZE; i++) {
417 InitializeListHead(&switchContext->pidHashArray[i]);
418 }
419
4a3c9b70 420 NdisAllocateSpinLock(&(switchContext->pidHashLock));
c803536e
SS
421 switchContext->isActivated = FALSE;
422 switchContext->isActivateFailed = FALSE;
423 switchContext->dpNo = OVS_DP_NUMBER;
c803536e 424 ovsTimeIncrementPerTick = KeQueryTimeIncrement() / 10000;
6c4e7adb 425
c803536e
SS
426 OVS_LOG_TRACE("Exit: Succesfully initialized switchContext: %p",
427 switchContext);
428 return NDIS_STATUS_SUCCESS;
429}
430
431static VOID
3a6de110 432OvsUninitSwitchContext(POVS_SWITCH_CONTEXT switchContext)
6c4e7adb
SV
433{
434 OvsReleaseSwitchContext(switchContext);
435}
436
e1e29b26
NR
437/*
438 * --------------------------------------------------------------------------
439 * Frees up the contents of and also the switch context.
440 * --------------------------------------------------------------------------
441 */
442static VOID
6c4e7adb 443OvsDeleteSwitchContext(POVS_SWITCH_CONTEXT switchContext)
c803536e
SS
444{
445 OVS_LOG_TRACE("Enter: Delete switchContext:%p", switchContext);
446
447 /* We need to do cleanup for tunnel port here. */
25e39a60 448 ASSERT(switchContext->numHvVports == 0);
35f20164 449 ASSERT(switchContext->numNonHvVports == 0);
c803536e
SS
450
451 NdisFreeRWLock(switchContext->dispatchLock);
3a6de110 452 switchContext->dispatchLock = NULL;
4a3c9b70 453 NdisFreeSpinLock(&(switchContext->pidHashLock));
ba7f9d90
SV
454 OvsFreeMemoryWithTag(switchContext->ovsPortNameHashArray,
455 OVS_SWITCH_POOL_TAG);
3a6de110 456 switchContext->ovsPortNameHashArray = NULL;
ba7f9d90
SV
457 OvsFreeMemoryWithTag(switchContext->portIdHashArray,
458 OVS_SWITCH_POOL_TAG);
3a6de110 459 switchContext->portIdHashArray = NULL;
ba7f9d90
SV
460 OvsFreeMemoryWithTag(switchContext->portNoHashArray,
461 OVS_SWITCH_POOL_TAG);
3a6de110 462 switchContext->portNoHashArray = NULL;
ba7f9d90
SV
463 OvsFreeMemoryWithTag(switchContext->pidHashArray,
464 OVS_SWITCH_POOL_TAG);
3a6de110 465 switchContext->pidHashArray = NULL;
c803536e
SS
466 OvsDeleteFlowTable(&switchContext->datapath);
467 OvsCleanupBufferPool(switchContext);
e1e29b26
NR
468
469 OvsFreeMemoryWithTag(switchContext, OVS_SWITCH_POOL_TAG);
c803536e
SS
470 OVS_LOG_TRACE("Exit: Delete switchContext: %p", switchContext);
471}
472
6c4e7adb
SV
473VOID
474OvsReleaseSwitchContext(POVS_SWITCH_CONTEXT switchContext)
475{
476 LONG ref = 0;
477 LONG newRef = 0;
478 LONG icxRef = 0;
479
480 do {
481 ref = gOvsSwitchContextRefCount;
482 newRef = (0 == ref) ? 0 : ref - 1;
483 icxRef = InterlockedCompareExchange(&gOvsSwitchContextRefCount,
484 newRef,
485 ref);
486 } while (icxRef != ref);
487
488 if (ref == 1) {
489 OvsDeleteSwitchContext(switchContext);
490 }
491}
492
493BOOLEAN
494OvsAcquireSwitchContext(VOID)
495{
496 LONG ref = 0;
497 LONG newRef = 0;
498 LONG icxRef = 0;
499 BOOLEAN ret = FALSE;
500
501 do {
502 ref = gOvsSwitchContextRefCount;
503 newRef = (0 == ref) ? 0 : ref + 1;
504 icxRef = InterlockedCompareExchange(&gOvsSwitchContextRefCount,
505 newRef,
506 ref);
507 } while (icxRef != ref);
508
509 if (ref != 0) {
510 ret = TRUE;
511 }
512
513 return ret;
514}
515
c803536e
SS
516/*
517 * --------------------------------------------------------------------------
518 * This function activates the switch by initializing it with all the runtime
519 * state. First it queries all of the MAC addresses set as custom switch policy
520 * to allow sends from, and adds tme to the property list. Then it queries the
521 * NIC list and verifies it can support all of the NICs currently connected to
522 * the switch, and adds the NICs to the NIC list.
523 * --------------------------------------------------------------------------
524 */
525static NDIS_STATUS
526OvsActivateSwitch(POVS_SWITCH_CONTEXT switchContext)
527{
528 NDIS_STATUS status;
529
530 ASSERT(!switchContext->isActivated);
531
532 OVS_LOG_TRACE("Enter: activate switch %p, dpNo: %ld",
533 switchContext, switchContext->dpNo);
534
535 status = OvsAddConfiguredSwitchPorts(switchContext);
536
537 if (status != NDIS_STATUS_SUCCESS) {
538 OVS_LOG_WARN("Failed to add configured switch ports");
539 goto cleanup;
540
541 }
542 status = OvsInitConfiguredSwitchNics(switchContext);
543
544 if (status != NDIS_STATUS_SUCCESS) {
545 OVS_LOG_WARN("Failed to add configured vports");
546 OvsClearAllSwitchVports(switchContext);
547 goto cleanup;
548 }
549 switchContext->isActivated = TRUE;
550 OvsPostEvent(OVS_DEFAULT_PORT_NO, OVS_DEFAULT_EVENT_STATUS);
551
552cleanup:
553 OVS_LOG_TRACE("Exit: activate switch:%p, isActivated: %s, status = %lx",
554 switchContext,
555 (switchContext->isActivated ? "TRUE" : "FALSE"), status);
556 return status;
557}
558
c803536e
SS
559
560/*
561 * --------------------------------------------------------------------------
562 * Implements filter driver's FilterNetPnPEvent function.
563 * --------------------------------------------------------------------------
564 */
565NDIS_STATUS
566OvsExtNetPnPEvent(NDIS_HANDLE filterModuleContext,
567 PNET_PNP_EVENT_NOTIFICATION netPnPEvent)
568{
569 NDIS_STATUS status = NDIS_STATUS_SUCCESS;
570 POVS_SWITCH_CONTEXT switchContext = (POVS_SWITCH_CONTEXT)filterModuleContext;
571 BOOLEAN switchActive;
572
573 OVS_LOG_TRACE("Enter: filterModuleContext: %p, NetEvent: %d",
574 filterModuleContext, (netPnPEvent->NetPnPEvent).NetEvent);
575 /*
576 * The only interesting event is the NetEventSwitchActivate. It provides
577 * an asynchronous notification of the switch completing activation.
578 */
579 if (netPnPEvent->NetPnPEvent.NetEvent == NetEventSwitchActivate) {
580 status = OvsQuerySwitchActivationComplete(switchContext, &switchActive);
581 if (status != NDIS_STATUS_SUCCESS) {
582 switchContext->isActivateFailed = TRUE;
583 } else {
584 ASSERT(switchContext->isActivated == FALSE);
c803536e
SS
585 if (switchContext->isActivated == FALSE && switchActive == TRUE) {
586 status = OvsActivateSwitch(switchContext);
587 OVS_LOG_TRACE("OvsExtNetPnPEvent: activated switch: %p "
588 "status: %s", switchContext,
589 status ? "TRUE" : "FALSE");
590 }
591 }
592 }
593
594 if (status == NDIS_STATUS_SUCCESS) {
595 status = NdisFNetPnPEvent(switchContext->NdisFilterHandle,
596 netPnPEvent);
597 }
598 OVS_LOG_TRACE("Exit: OvsExtNetPnPEvent");
599
600 return status;
601}