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