Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1917 lines
51 KiB

  1. /*++
  2. Copyright (c) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. cmvc.c
  5. Abstract:
  6. Author:
  7. Charlie Wickham (charlwi) 13-Sep-1996.
  8. Rajesh Sundaram (rajeshsu) 01-Aug-1998.
  9. Environment:
  10. Kernel Mode
  11. Revision History:
  12. --*/
  13. #include "psched.h"
  14. #pragma hdrstop
  15. /* External */
  16. /* Static */
  17. /* Forward */
  18. NDIS_STATUS
  19. RemoveDiffservMapping(
  20. PGPC_CLIENT_VC Vc
  21. );
  22. NDIS_STATUS
  23. ProcessDiffservFlow(
  24. PGPC_CLIENT_VC Vc,
  25. PCO_CALL_MANAGER_PARAMETERS CallParameters);
  26. NDIS_STATUS
  27. ValidateCallParameters(
  28. PGPC_CLIENT_VC Vc,
  29. PCO_CALL_MANAGER_PARAMETERS CallParameters
  30. );
  31. NDIS_STATUS
  32. AcquireFlowResources(
  33. PGPC_CLIENT_VC Vc,
  34. PCO_CALL_MANAGER_PARAMETERS NewCallParams,
  35. PCO_CALL_MANAGER_PARAMETERS OldCallParams,
  36. PULONG RemainingBandWidthChanged
  37. );
  38. VOID
  39. ReturnFlowResources(
  40. PGPC_CLIENT_VC Vc,
  41. PULONG RemainingBandWidthChanged
  42. );
  43. VOID
  44. CancelAcquiredFlowResources(
  45. PGPC_CLIENT_VC Vc
  46. );
  47. /* End Forward */
  48. NDIS_STATUS
  49. CmCreateVc(PGPC_CLIENT_VC *GpcClientVc,
  50. PADAPTER Adapter,
  51. PPS_WAN_LINK WanLink,
  52. PCO_CALL_PARAMETERS CallParams,
  53. GPC_HANDLE GpcCfInfoHandle,
  54. PCF_INFO_QOS CfInfoPtr,
  55. GPC_CLIENT_HANDLE ClientContext)
  56. {
  57. PGPC_CLIENT_VC Vc;
  58. *GpcClientVc = NULL;
  59. PsAllocFromLL(&Vc, &GpcClientVcLL, GpcClientVc);
  60. if(Vc == NULL)
  61. {
  62. return NDIS_STATUS_RESOURCES;
  63. }
  64. InitGpcClientVc(Vc, 0, Adapter);
  65. SetLLTag(Vc, GpcClientVc);
  66. //
  67. // Allocate space for the instance name for the Vc.
  68. //
  69. PsAllocatePool(Vc->InstanceName.Buffer,
  70. Adapter->WMIInstanceName.Length + VcPrefix.Length + INSTANCE_ID_SIZE,
  71. PsMiscTag);
  72. if(!Vc->InstanceName.Buffer)
  73. {
  74. PsFreeToLL(Vc, &GpcClientVcLL, GpcClientVc);
  75. return NDIS_STATUS_RESOURCES;
  76. }
  77. Vc->CfInfoHandle = GpcCfInfoHandle;
  78. Vc->CfType = ClientContext;
  79. Vc->CfInfoQoS = CfInfoPtr;
  80. Vc->CallParameters = CallParams;
  81. PS_LOCK(&Adapter->Lock);
  82. if(Adapter->PsMpState == AdapterStateRunning)
  83. {
  84. //
  85. // Insert the Vc in the adapter list
  86. //
  87. InsertHeadList(&Adapter->GpcClientVcList, &Vc->Linkage);
  88. PS_UNLOCK(&Adapter->Lock);
  89. }
  90. else
  91. {
  92. PsFreePool(Vc->InstanceName.Buffer);
  93. PsFreeToLL(Vc, &GpcClientVcLL, GpcClientVc);
  94. PS_UNLOCK(&Adapter->Lock);
  95. return GPC_STATUS_NOTREADY;
  96. }
  97. if(WanLink) {
  98. Vc->Flags |= GPC_WANLINK_VC;
  99. //
  100. // We need to link the VC to the WanLink. This has to be done because
  101. // we have to clean up when we get a NDIS_STATUS_WAN_LINE_DOWN
  102. //
  103. Vc->AdapterStats = &WanLink->Stats;
  104. Vc->WanLink = WanLink;
  105. Vc->PsPipeContext = WanLink->PsPipeContext;
  106. Vc->PsComponent = WanLink->PsComponent;
  107. }
  108. else
  109. {
  110. Vc->AdapterStats = &Adapter->Stats;
  111. Vc->PsPipeContext = Adapter->PsPipeContext;
  112. Vc->PsComponent = Adapter->PsComponent;
  113. }
  114. *GpcClientVc = Vc;
  115. return NDIS_STATUS_SUCCESS;
  116. } // CmCreateVc
  117. BOOLEAN
  118. IsIsslowFlow(
  119. IN PGPC_CLIENT_VC Vc,
  120. IN PCO_CALL_PARAMETERS CallParameters
  121. )
  122. {
  123. LONG ParamsLength;
  124. LPQOS_OBJECT_HDR QoSObject;
  125. PADAPTER Adapter = Vc->Adapter;
  126. PCO_MEDIA_PARAMETERS CallMgrParams = CallParameters->MediaParameters;
  127. ULONGLONG i,j,k;
  128. ParamsLength = (LONG)CallMgrParams->MediaSpecific.Length;
  129. QoSObject = (LPQOS_OBJECT_HDR)CallMgrParams->MediaSpecific.Parameters;
  130. while(ParamsLength > 0)
  131. {
  132. if(QoSObject->ObjectType == QOS_OBJECT_WAN_MEDIA)
  133. {
  134. if((Vc->WanLink->LinkSpeed <= Adapter->ISSLOWLinkSpeed) &&
  135. (CallParameters->CallMgrParameters->Transmit.ServiceType != SERVICETYPE_BESTEFFORT))
  136. {
  137. i = (ULONG) Adapter->ISSLOWTokenRate * (ULONG) CallParameters->CallMgrParameters->Transmit.MaxSduSize;
  138. j = (ULONG) Adapter->ISSLOWPacketSize * (ULONG) CallParameters->CallMgrParameters->Transmit.TokenRate;
  139. k = (ULONG) Adapter->ISSLOWTokenRate * (ULONG)Adapter->ISSLOWPacketSize;
  140. if((i+j)<k)
  141. return TRUE;
  142. }
  143. return FALSE;
  144. }
  145. else
  146. {
  147. if( ((LONG)QoSObject->ObjectLength <= 0) ||
  148. ((LONG)QoSObject->ObjectLength > ParamsLength) )
  149. {
  150. return(FALSE);
  151. }
  152. ParamsLength -= QoSObject->ObjectLength;
  153. QoSObject = (LPQOS_OBJECT_HDR)((UINT_PTR)QoSObject + QoSObject->ObjectLength);
  154. }
  155. }
  156. return FALSE;
  157. }
  158. NDIS_STATUS
  159. CmMakeCall(
  160. IN PGPC_CLIENT_VC Vc
  161. )
  162. {
  163. ULONG CmParamsLength;
  164. NDIS_STATUS Status;
  165. ULONG RemainingBandWidthChanged;
  166. PADAPTER Adapter = Vc->Adapter;
  167. PCO_CALL_PARAMETERS CallParameters = Vc->CallParameters;
  168. //
  169. // Validate parameters
  170. //
  171. Status = ValidateCallParameters(Vc, CallParameters->CallMgrParameters);
  172. if(Status != NDIS_STATUS_SUCCESS)
  173. {
  174. PsDbgOut(DBG_INFO,
  175. DBG_VC,
  176. ("[CmMakeCall]: Vc %08X, invalid QoS parameters\n",
  177. Vc));
  178. return Status;
  179. }
  180. //
  181. // make sure we can admit the flow onto our adapter. if this
  182. // succeeds, the resources are committed and we'll have to call
  183. // CancelAcquiredFlowResources to return them.
  184. //
  185. Status = AcquireFlowResources(Vc,
  186. CallParameters->CallMgrParameters,
  187. NULL,
  188. &RemainingBandWidthChanged);
  189. if(Status != NDIS_STATUS_SUCCESS)
  190. {
  191. PsDbgOut(DBG_INFO,
  192. DBG_VC,
  193. ("[CmMakeCall]: Vc %08X, no flow resc\n",
  194. Vc));
  195. return Status;
  196. }
  197. //
  198. // In the integrated call manager/miniport model, the activation
  199. // is internal. Activating the Vc consists of adding the flow to the
  200. // scheduler. If it succeeds, we will later call NdisMCmActivateVc,
  201. // just as a courtesy, to notify NDIS.
  202. //
  203. if( Adapter->MediaType == NdisMediumWan &&
  204. !IsBestEffortVc(Vc) &&
  205. IsIsslowFlow( Vc, CallParameters ) )
  206. {
  207. // Need to do this before we add a flow to the sched components.
  208. Vc->Flags |= GPC_ISSLOW_FLOW;
  209. }
  210. Status = AddFlowToScheduler(NEW_VC, Vc, CallParameters, 0);
  211. // Let's revert it back, to avoid any side effects..
  212. Vc->Flags = Vc->Flags & ~GPC_ISSLOW_FLOW;
  213. if(Status != NDIS_STATUS_SUCCESS)
  214. {
  215. PsDbgOut(DBG_FAILURE,
  216. DBG_VC,
  217. ("[CmMakeCall]: Vc %08X, AddFlowToScheduler failed %08X\n",
  218. Vc,
  219. Status));
  220. CancelAcquiredFlowResources(Vc);
  221. return(Status);
  222. }
  223. //
  224. // A flow has been added to psched after this point. So, whenever the Vc goes away, Psched's flow
  225. // has to be removed from an explicit call.
  226. //
  227. Vc->bRemoveFlow = TRUE;
  228. //
  229. // If there is an NDIS 5.0, connection oriented driver below us, then
  230. // we need to call it, with the call parameters, to complete the VC
  231. // setup.
  232. //
  233. if(Adapter->MediaType == NdisMediumWan &&
  234. !IsBestEffortVc(Vc))
  235. {
  236. Status = WanMakeCall(Vc, CallParameters);
  237. PsAssert(Status == NDIS_STATUS_PENDING);
  238. return Status;
  239. }
  240. else
  241. {
  242. //
  243. // if we made it this far, the MakeCall succeeded!
  244. //
  245. Status = ProcessDiffservFlow(Vc, CallParameters->CallMgrParameters);
  246. if(Status != NDIS_STATUS_SUCCESS)
  247. {
  248. PsDbgOut(DBG_FAILURE,
  249. DBG_VC,
  250. ("[CmMakeCall]: Vc %08X, AddDiffservMapping failed %08X\n", Vc, Status));
  251. CancelAcquiredFlowResources(Vc);
  252. return Status;
  253. }
  254. if(TRUE == RemainingBandWidthChanged)
  255. {
  256. LONG RemainingBandWidth;
  257. PS_LOCK(&Adapter->Lock);
  258. RemainingBandWidth = (LONG) Adapter->RemainingBandWidth;
  259. PS_UNLOCK(&Adapter->Lock);
  260. PsTcNotify(Adapter, 0, OID_QOS_REMAINING_BANDWIDTH, &RemainingBandWidth, sizeof(LONG));
  261. }
  262. Vc->TokenRateChange = 0;
  263. return NDIS_STATUS_SUCCESS;
  264. }
  265. }
  266. VOID
  267. CompleteMakeCall(
  268. PGPC_CLIENT_VC Vc,
  269. PCO_CALL_PARAMETERS CallParameters,
  270. NDIS_STATUS Status
  271. )
  272. {
  273. PADAPTER Adapter = Vc->Adapter;
  274. PsAssert(Adapter->MediaType == NdisMediumWan);
  275. PsAssert(!IsBestEffortVc(Vc));
  276. if(Status != NDIS_STATUS_SUCCESS)
  277. {
  278. CancelAcquiredFlowResources(Vc);
  279. }
  280. else
  281. {
  282. Status = ProcessDiffservFlow(Vc, CallParameters->CallMgrParameters);
  283. if(Status != NDIS_STATUS_SUCCESS)
  284. {
  285. PsDbgOut(DBG_FAILURE,
  286. DBG_VC,
  287. ("[CompleteMakeCall]: Vc %08X, AddDiffservMapping failed %08X\n", Vc, Status));
  288. CancelAcquiredFlowResources(Vc);
  289. }
  290. }
  291. Vc->TokenRateChange = 0;
  292. CmMakeCallComplete(Status, Vc, CallParameters);
  293. }
  294. NDIS_STATUS
  295. CmModifyCall(
  296. IN PGPC_CLIENT_VC Vc
  297. )
  298. /*++
  299. Routine Description:
  300. Modify the QoS of an existing flow based on the supplied call params.
  301. First see if the request can be handled locally.
  302. Arguments:
  303. See the DDK...
  304. Return Values:
  305. NDIS_STATUS_SUCCESS if everything worked ok.
  306. --*/
  307. {
  308. NDIS_STATUS Status;
  309. ULONG CmParamsLength;
  310. PCO_CALL_PARAMETERS CallParameters;
  311. PADAPTER Adapter;
  312. ULONG RemainingBandWidthChanged;
  313. Adapter = Vc->Adapter;
  314. PsStructAssert(Adapter);
  315. PsAssert(Vc->TokenRateChange == 0);
  316. //
  317. // Validate parameters
  318. //
  319. CallParameters = Vc->ModifyCallParameters;
  320. Status = ValidateCallParameters(Vc, CallParameters->CallMgrParameters);
  321. if(Status != NDIS_STATUS_SUCCESS)
  322. {
  323. PsDbgOut(DBG_INFO,
  324. DBG_VC,
  325. ("[CmModifyCallQoS]: Vc %08X, invalid QoS parameters\n",
  326. Vc));
  327. return Status;
  328. }
  329. //
  330. // make sure we can admit the flow onto our adapter. if this
  331. // succeeds, the resources are committed and we'll have to call
  332. // CancelAcquiredFlowResources to return them.
  333. //
  334. Status = AcquireFlowResources(Vc,
  335. CallParameters->CallMgrParameters,
  336. Vc->CallParameters->CallMgrParameters,
  337. &RemainingBandWidthChanged);
  338. if(Status != NDIS_STATUS_SUCCESS){
  339. PsDbgOut(DBG_INFO,
  340. DBG_VC,
  341. ("[CmModifyCallQoS]: Vc %08X, no flow resc\n",
  342. Vc));
  343. return Status;
  344. }
  345. Status = AddFlowToScheduler(MODIFY_VC, Vc, CallParameters, Vc->CallParameters);
  346. if(Status != NDIS_STATUS_SUCCESS){
  347. PsDbgOut(DBG_FAILURE,
  348. DBG_VC,
  349. ("[CmModifyCallQoS]: Vc %08X, failed %08X\n",
  350. Vc,
  351. Status));
  352. //
  353. // Free the copy we made, Cancel the committed resources.
  354. //
  355. CancelAcquiredFlowResources(Vc);
  356. return(Status);
  357. }
  358. //
  359. // If there is an NDIS 5.0, connection oriented driver below us, then
  360. // we need to call it, with the call parameters, to complete the VC
  361. // setup.
  362. //
  363. if(Adapter->MediaType == NdisMediumWan){
  364. Status = WanModifyCall(Vc, CallParameters);
  365. PsAssert(Status == NDIS_STATUS_PENDING);
  366. return(Status);
  367. }
  368. else
  369. {
  370. //
  371. // if we made it this far, the ModifyCallQoS succeeded!
  372. //
  373. Status = ProcessDiffservFlow(Vc, CallParameters->CallMgrParameters);
  374. if(Status != NDIS_STATUS_SUCCESS) {
  375. PsDbgOut(DBG_FAILURE,
  376. DBG_VC,
  377. ("[CmModifyCallQos]: Vc %08X, AddDiffservMapping failed %08X\n", Vc, Status));
  378. //
  379. // Undo the add flow done above, by reversing the new and old parameters.
  380. //
  381. ValidateCallParameters(Vc, Vc->CallParameters->CallMgrParameters);
  382. AddFlowToScheduler(MODIFY_VC, Vc, Vc->CallParameters, CallParameters);
  383. CancelAcquiredFlowResources(Vc);
  384. return Status;
  385. }
  386. if(TRUE == RemainingBandWidthChanged) {
  387. LONG RemainingBandWidth;
  388. PS_LOCK(&Adapter->Lock);
  389. RemainingBandWidth = (LONG) Adapter->RemainingBandWidth;
  390. PS_UNLOCK(&Adapter->Lock);
  391. PsTcNotify(Adapter, 0, OID_QOS_REMAINING_BANDWIDTH, &RemainingBandWidth, sizeof(LONG));
  392. }
  393. Vc->TokenRateChange = 0;
  394. return(NDIS_STATUS_SUCCESS);
  395. }
  396. } // CmModifyCallQoS
  397. VOID
  398. ModifyCallComplete(
  399. PGPC_CLIENT_VC Vc,
  400. PCO_CALL_PARAMETERS CallParameters,
  401. NDIS_STATUS Status
  402. )
  403. {
  404. PADAPTER Adapter = Vc->Adapter;
  405. PsAssert(Adapter->MediaType == NdisMediumWan);
  406. PsAssert(!IsBestEffortVc(Vc));
  407. if(Status != NDIS_STATUS_SUCCESS) {
  408. //
  409. // Undo the add flow done above, by reversing the new and old parameters.
  410. //
  411. ValidateCallParameters(Vc, Vc->CallParameters->CallMgrParameters);
  412. Status = AddFlowToScheduler(MODIFY_VC, Vc, Vc->CallParameters, CallParameters);
  413. CancelAcquiredFlowResources(Vc);
  414. }
  415. else {
  416. Status = ProcessDiffservFlow(Vc, CallParameters->CallMgrParameters);
  417. if(Status != NDIS_STATUS_SUCCESS) {
  418. PsDbgOut(DBG_FAILURE,
  419. DBG_VC,
  420. ("[CmModifyCallQos]: Vc %08X, AddDiffservMapping failed %08X\n", Vc, Status));
  421. //
  422. // Undo the add flow done above, by reversing the new and old parameters.
  423. //
  424. ValidateCallParameters(Vc, Vc->CallParameters->CallMgrParameters);
  425. AddFlowToScheduler(MODIFY_VC, Vc, Vc->CallParameters, CallParameters);
  426. CancelAcquiredFlowResources(Vc);
  427. }
  428. }
  429. Vc->TokenRateChange = 0;
  430. CmModifyCallComplete(Status, Vc, CallParameters);
  431. }
  432. NDIS_STATUS
  433. CmCloseCall(
  434. PGPC_CLIENT_VC Vc
  435. )
  436. {
  437. NDIS_STATUS Status;
  438. PADAPTER Adapter = Vc->Adapter;
  439. ULONG RemainingBandWidthChanged;
  440. PsStructAssert(Adapter);
  441. //
  442. // Here, we used to call RemoveFlowFromScheduler, which used to call "DeleteFlow". Instead, we will
  443. // call a new interface "EmptyPacketsFromScheduler", which will call "EmptyFlow" to empty all the
  444. // packets queued up in each of the components corresponding to this flow.
  445. //
  446. EmptyPacketsFromScheduler( Vc );
  447. RemoveDiffservMapping(Vc);
  448. ReturnFlowResources(Vc, &RemainingBandWidthChanged);
  449. if(TRUE == RemainingBandWidthChanged) {
  450. LONG RemainingBandWidth;
  451. PS_LOCK(&Adapter->Lock);
  452. RemainingBandWidth = (LONG) Adapter->RemainingBandWidth;
  453. PS_UNLOCK(&Adapter->Lock);
  454. PsTcNotify(Adapter, 0, OID_QOS_REMAINING_BANDWIDTH, &RemainingBandWidth, sizeof(LONG));
  455. }
  456. if(!IsBestEffortVc(Vc))
  457. {
  458. CmCloseCallComplete(NDIS_STATUS_SUCCESS, Vc);
  459. }
  460. else
  461. {
  462. DerefClVc(Vc);
  463. }
  464. return NDIS_STATUS_PENDING;
  465. }
  466. NDIS_STATUS
  467. CmDeleteVc(
  468. IN PGPC_CLIENT_VC Vc
  469. )
  470. {
  471. PsAssert(Vc->RefCount == 0);
  472. if(Vc->InstanceName.Buffer) {
  473. PsFreePool(Vc->InstanceName.Buffer);
  474. }
  475. if( Vc->bRemoveFlow)
  476. {
  477. Vc->bRemoveFlow = FALSE;
  478. RemoveFlowFromScheduler(Vc);
  479. }
  480. if(Vc->PsFlowContext) {
  481. if(Vc->Adapter->MediaType == NdisMediumWan) {
  482. if(Vc->PsFlowContext != Vc->WanLink->BestEffortVc.PsFlowContext) {
  483. PsFreePool(Vc->PsFlowContext);
  484. }
  485. else {
  486. if(Vc == &Vc->WanLink->BestEffortVc) {
  487. PsFreePool(Vc->PsFlowContext);
  488. }
  489. }
  490. }
  491. else {
  492. if(Vc->PsFlowContext != Vc->Adapter->BestEffortVc.PsFlowContext) {
  493. PsFreePool(Vc->PsFlowContext);
  494. }
  495. else {
  496. if(Vc == &Vc->Adapter->BestEffortVc) {
  497. PsFreePool(Vc->PsFlowContext);
  498. }
  499. }
  500. }
  501. }
  502. NdisFreeSpinLock(&Vc->Lock);
  503. NdisFreeSpinLock(&Vc->BytesScheduledLock);
  504. NdisFreeSpinLock(&Vc->BytesTransmittedLock);
  505. if(Vc->CallParameters){
  506. PsFreePool(Vc->CallParameters);
  507. Vc->CallParameters = NULL;
  508. }
  509. if(!IsBestEffortVc(Vc))
  510. {
  511. PS_LOCK(&Vc->Adapter->Lock);
  512. RemoveEntryList(&Vc->Linkage);
  513. PS_UNLOCK(&Vc->Adapter->Lock);
  514. if(Vc->Flags & GPC_WANLINK_VC)
  515. {
  516. REFDEL(&Vc->WanLink->RefCount, FALSE, 'WANV');
  517. }
  518. REFDEL(&Vc->Adapter->RefCount, FALSE, 'ADVC');
  519. PsFreeToLL(Vc, &GpcClientVcLL, GpcClientVc);
  520. }
  521. else
  522. {
  523. PADAPTER Adapter = Vc->Adapter;
  524. if(Vc->Flags & GPC_WANLINK_VC)
  525. {
  526. REFDEL(&Vc->WanLink->RefCount, FALSE, 'WANV');
  527. }
  528. REFDEL(&Adapter->RefCount, FALSE, 'ADVC');
  529. }
  530. return(NDIS_STATUS_SUCCESS);
  531. } // CmDeleteVc
  532. VOID
  533. FillInCmParams(
  534. PCO_CALL_MANAGER_PARAMETERS CmParams,
  535. SERVICETYPE ServiceType,
  536. ULONG TokenRate,
  537. ULONG PeakBandwidth,
  538. ULONG TokenBucketSize,
  539. ULONG DSMode,
  540. ULONG Priority)
  541. {
  542. PCO_SPECIFIC_PARAMETERS SpecificParameters;
  543. QOS_SD_MODE * QoSObjectSDMode;
  544. QOS_PRIORITY * QoSObjectPriority;
  545. QOS_OBJECT_HDR * QoSObjectHdr;
  546. CmParams->Transmit.ServiceType = ServiceType;
  547. CmParams->Transmit.TokenRate = TokenRate;
  548. CmParams->Transmit.PeakBandwidth = PeakBandwidth;
  549. CmParams->Transmit.TokenBucketSize = TokenBucketSize;
  550. CmParams->CallMgrSpecific.ParamType = PARAM_TYPE_GQOS_INFO;
  551. CmParams->CallMgrSpecific.Length = 0;
  552. SpecificParameters =
  553. (PCO_SPECIFIC_PARAMETERS)&CmParams->CallMgrSpecific.Parameters;
  554. if(DSMode != QOS_UNSPECIFIED){
  555. CmParams->CallMgrSpecific.Length += sizeof(QOS_SD_MODE);
  556. QoSObjectSDMode = (QOS_SD_MODE *)SpecificParameters;
  557. QoSObjectSDMode->ObjectHdr.ObjectType = QOS_OBJECT_SD_MODE;
  558. QoSObjectSDMode->ObjectHdr.ObjectLength = sizeof(QOS_SD_MODE);
  559. QoSObjectSDMode->ShapeDiscardMode = DSMode;
  560. (QOS_SD_MODE *)SpecificParameters++;
  561. }
  562. if(Priority != QOS_UNSPECIFIED){
  563. CmParams->CallMgrSpecific.Length += sizeof(QOS_PRIORITY);
  564. QoSObjectPriority = (QOS_PRIORITY *)SpecificParameters;
  565. QoSObjectPriority->ObjectHdr.ObjectType = QOS_OBJECT_PRIORITY;
  566. QoSObjectPriority->ObjectHdr.ObjectLength = sizeof(QOS_PRIORITY);
  567. QoSObjectPriority->SendPriority = (UCHAR)Priority;
  568. (QOS_PRIORITY *)SpecificParameters++;
  569. }
  570. QoSObjectHdr = (QOS_OBJECT_HDR *)SpecificParameters;
  571. QoSObjectHdr->ObjectType = QOS_OBJECT_END_OF_LIST;
  572. QoSObjectHdr->ObjectLength = sizeof(QOS_OBJECT_HDR);
  573. }
  574. NDIS_STATUS
  575. ValidateCallParameters(
  576. PGPC_CLIENT_VC Vc,
  577. PCO_CALL_MANAGER_PARAMETERS CallParameters
  578. )
  579. {
  580. ULONG TokenRate = CallParameters->Transmit.TokenRate;
  581. SERVICETYPE ServiceType = CallParameters->Transmit.ServiceType;
  582. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  583. UCHAR SendPriority;
  584. ULONG SDMode;
  585. ULONG PeakBandwidth;
  586. LONG ParamsLength;
  587. LPQOS_OBJECT_HDR QoSObject;
  588. ULONG Class;
  589. ULONG DSFieldCount;
  590. LPQOS_DIFFSERV_RULE pDiffServRule;
  591. ULONG i;
  592. ULONG ShapingRate;
  593. ParamsLength = (LONG)CallParameters->CallMgrSpecific.Length;
  594. PeakBandwidth = CallParameters->Transmit.PeakBandwidth;
  595. //
  596. // By default, we want to shape to the TokenRate
  597. //
  598. Vc->ShapeTokenRate = TokenRate;
  599. QoSObject = (LPQOS_OBJECT_HDR)CallParameters->CallMgrSpecific.Parameters;
  600. while(ParamsLength > 0){
  601. switch(QoSObject->ObjectType){
  602. case QOS_OBJECT_TRAFFIC_CLASS:
  603. Class = (((LPQOS_TRAFFIC_CLASS)QoSObject)->TrafficClass);
  604. if(Class > USER_PRIORITY_MAX_VALUE)
  605. {
  606. return QOS_STATUS_INVALID_TRAFFIC_CLASS;
  607. }
  608. break;
  609. case QOS_OBJECT_DS_CLASS:
  610. Class = (((LPQOS_DS_CLASS)QoSObject)->DSField);
  611. if(Class > PREC_MAX_VALUE)
  612. {
  613. return QOS_STATUS_INVALID_DS_CLASS;
  614. }
  615. break;
  616. case QOS_OBJECT_SHAPING_RATE:
  617. ShapingRate = (((LPQOS_SHAPING_RATE)QoSObject)->ShapingRate);
  618. if(ShapingRate == 0 || ShapingRate > TokenRate)
  619. {
  620. return QOS_STATUS_INVALID_SHAPE_RATE;
  621. }
  622. else
  623. {
  624. //
  625. // If this QoS object is present, we want to shape to this
  626. // rate.
  627. //
  628. Vc->ShapeTokenRate = ShapingRate;
  629. }
  630. break;
  631. case QOS_OBJECT_DIFFSERV:
  632. DSFieldCount = (((LPQOS_DIFFSERV)QoSObject)->DSFieldCount);
  633. if(!DSFieldCount) {
  634. return QOS_STATUS_INVALID_DIFFSERV_FLOW;
  635. }
  636. pDiffServRule = ((LPQOS_DIFFSERV_RULE)((LPQOS_DIFFSERV)QoSObject)->DiffservRule);
  637. for(i=0; i<DSFieldCount; i++, pDiffServRule++) {
  638. if(pDiffServRule->InboundDSField > PREC_MAX_VALUE ||
  639. pDiffServRule->ConformingOutboundDSField > PREC_MAX_VALUE ||
  640. pDiffServRule->NonConformingOutboundDSField > PREC_MAX_VALUE ||
  641. pDiffServRule->ConformingUserPriority > USER_PRIORITY_MAX_VALUE ||
  642. pDiffServRule->NonConformingUserPriority > USER_PRIORITY_MAX_VALUE ) {
  643. return QOS_STATUS_INVALID_DIFFSERV_FLOW;
  644. }
  645. }
  646. break;
  647. case QOS_OBJECT_PRIORITY:
  648. SendPriority = ((LPQOS_PRIORITY)QoSObject)->SendPriority;
  649. if((SendPriority < 0) || (SendPriority > 7)){
  650. // bad priority value - reject
  651. return(QOS_STATUS_INVALID_QOS_PRIORITY);
  652. }
  653. break;
  654. case QOS_OBJECT_SD_MODE:
  655. SDMode = ((LPQOS_SD_MODE)QoSObject)->ShapeDiscardMode;
  656. //
  657. // Since SDMode is a ULONG, it can never be < TC_NONCONF_BORROW, which has a value of 0.
  658. // so, we just check to see if SDMode is > TC_NONCONF_BORROW_PLUS. This covers all cases.
  659. //
  660. if(SDMode > TC_NONCONF_BORROW_PLUS){
  661. // bad shape discard mode - reject
  662. return(QOS_STATUS_INVALID_SD_MODE);
  663. }
  664. if((SDMode > TC_NONCONF_BORROW) &&
  665. (TokenRate == UNSPECIFIED_RATE)){
  666. // must have TokenRate specified if any SDMode
  667. // other than TC_NONCONF_BORROW
  668. return(QOS_STATUS_INVALID_TOKEN_RATE);
  669. }
  670. break;
  671. // Pass any provider specific objects that we don't recognize
  672. }
  673. if(
  674. ((LONG)QoSObject->ObjectLength <= 0) ||
  675. ((LONG)QoSObject->ObjectLength > ParamsLength)
  676. ){
  677. return(QOS_STATUS_TC_OBJECT_LENGTH_INVALID);
  678. }
  679. ParamsLength -= QoSObject->ObjectLength;
  680. QoSObject = (LPQOS_OBJECT_HDR)((UINT_PTR)QoSObject +
  681. QoSObject->ObjectLength);
  682. }
  683. //
  684. // If there is a specified PeakBandwidth, it must be geq to the
  685. // TokenRate - meaning - there must be a TokenRate specified also.
  686. // This is reasonable for LAN, although ATM does allow a
  687. // PeakBandwidth to be specified with no TokenRate.
  688. //
  689. // We also reject a TokenRate of zero.
  690. //
  691. if(PeakBandwidth != UNSPECIFIED_RATE){
  692. if(TokenRate == UNSPECIFIED_RATE){
  693. return(QOS_STATUS_INVALID_PEAK_RATE);
  694. }
  695. if(TokenRate > PeakBandwidth){
  696. return(QOS_STATUS_INVALID_PEAK_RATE);
  697. }
  698. }
  699. if(TokenRate == 0){
  700. return(QOS_STATUS_INVALID_TOKEN_RATE);
  701. }
  702. switch(ServiceType){
  703. case SERVICETYPE_BESTEFFORT:
  704. case SERVICETYPE_NETWORK_CONTROL:
  705. case SERVICETYPE_QUALITATIVE:
  706. break;
  707. case SERVICETYPE_CONTROLLEDLOAD:
  708. case SERVICETYPE_GUARANTEED:
  709. // Must specify a TokenRate for these services
  710. if(TokenRate == QOS_UNSPECIFIED) {
  711. return(QOS_STATUS_INVALID_TOKEN_RATE);
  712. }
  713. break;
  714. default:
  715. return(QOS_STATUS_INVALID_SERVICE_TYPE);
  716. }
  717. return(Status);
  718. }
  719. NDIS_STATUS
  720. AcquireFlowResources(
  721. PGPC_CLIENT_VC Vc,
  722. PCO_CALL_MANAGER_PARAMETERS NewCallParams,
  723. PCO_CALL_MANAGER_PARAMETERS OldCallParams,
  724. PULONG RemainingBandWidthChanged
  725. )
  726. /*++
  727. Routine Description:
  728. See if this adapter can support the requested flow. If it can,
  729. NDIS_STATUS_SUCCESS is returned, indicating that the resources
  730. have been committed.
  731. Arguments:
  732. Vc - pointer to vc's context block
  733. NewCallParams - struct describing the flow to add or to modify to.
  734. OldCallParams - in case of a modify, this describes the old params.
  735. Return Value:
  736. NDIS_STATUS_SUCCESS if everything worked ok
  737. --*/
  738. {
  739. PADAPTER Adapter;
  740. ULONG OldTokenRate;
  741. SERVICETYPE OldServiceType;
  742. ULONG NewTokenRate = NewCallParams->Transmit.TokenRate;
  743. SERVICETYPE NewServiceType = NewCallParams->Transmit.ServiceType;
  744. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  745. PULONG RemainingBandWidth;
  746. PULONG NonBestEffortLimit;
  747. PPS_SPIN_LOCK Lock;
  748. Adapter = Vc->Adapter;
  749. PsStructAssert(Adapter);
  750. *RemainingBandWidthChanged = FALSE;
  751. if(Adapter->MediaType == NdisMediumWan && (!IsBestEffortVc(Vc)))
  752. {
  753. RemainingBandWidth = &Vc->WanLink->RemainingBandWidth;
  754. NonBestEffortLimit = &Vc->WanLink->NonBestEffortLimit;
  755. Lock = &Vc->WanLink->Lock;
  756. return NDIS_STATUS_SUCCESS;
  757. }
  758. else
  759. {
  760. RemainingBandWidth = &Adapter->RemainingBandWidth;
  761. NonBestEffortLimit = &Adapter->NonBestEffortLimit;
  762. Lock = &Adapter->Lock;
  763. }
  764. if(OldCallParams)
  765. {
  766. OldTokenRate = OldCallParams->Transmit.TokenRate;
  767. OldServiceType = OldCallParams->Transmit.ServiceType;
  768. }
  769. //
  770. // sanity check passed; now see if we have the resouces locally
  771. //
  772. // for best-effort flows, the token rate, for the purpose of
  773. // admission control, is considered to be zero
  774. //
  775. if(NewServiceType == SERVICETYPE_BESTEFFORT || NewServiceType == SERVICETYPE_NETWORK_CONTROL ||
  776. NewServiceType == SERVICETYPE_QUALITATIVE)
  777. {
  778. NewTokenRate = 0;
  779. }
  780. //
  781. // Handle add differently from a modify
  782. //
  783. if(!OldCallParams){
  784. PS_LOCK(Lock);
  785. if((((LONG)(*RemainingBandWidth)) < 0) || (NewTokenRate > *RemainingBandWidth)){
  786. PS_UNLOCK(Lock);
  787. return(NDIS_STATUS_RESOURCES);
  788. }
  789. else{
  790. if(NewTokenRate) {
  791. *RemainingBandWidthChanged = TRUE;
  792. }
  793. *RemainingBandWidth -= NewTokenRate;
  794. //
  795. // Record the change we made, in case we have
  796. // to cancel the addition.
  797. //
  798. Vc->TokenRateChange = NewTokenRate;
  799. Vc->RemainingBandwidthIncreased = FALSE;
  800. PsAssert((*RemainingBandWidth <= *NonBestEffortLimit));
  801. PS_UNLOCK(Lock);
  802. }
  803. }
  804. else{
  805. //
  806. // it's a modify
  807. //
  808. // If the OldServiceType is best-effort,
  809. // then the OldTokenRate can be considered
  810. // to be zero, for the purpose of admission control.
  811. //
  812. if(OldServiceType == SERVICETYPE_BESTEFFORT ||
  813. OldServiceType == SERVICETYPE_NETWORK_CONTROL ||
  814. OldServiceType == SERVICETYPE_QUALITATIVE)
  815. {
  816. OldTokenRate = 0;
  817. }
  818. PS_LOCK(Lock);
  819. if(NewTokenRate != OldTokenRate){
  820. if((((LONG) *RemainingBandWidth) < 0 )||
  821. ((NewTokenRate > OldTokenRate) &&
  822. ((NewTokenRate - OldTokenRate) >
  823. (*RemainingBandWidth)))){
  824. //
  825. // asked for more and none was available
  826. //
  827. PS_UNLOCK( Lock );
  828. return(NDIS_STATUS_RESOURCES);
  829. }
  830. else{
  831. //
  832. // either asked for less or rate increment was available
  833. //
  834. *RemainingBandWidth -= NewTokenRate;
  835. *RemainingBandWidth += OldTokenRate;
  836. if((NewTokenRate != 0) || (OldTokenRate != 0)) {
  837. *RemainingBandWidthChanged = TRUE;
  838. }
  839. //
  840. // Now we've acquired the resources. If
  841. // the VC activation fails for any reason,
  842. // we'll need to return resources. We should
  843. // return the difference between the old token
  844. // rate and the new token rate, not the new token
  845. // rate.
  846. //
  847. if(NewTokenRate > OldTokenRate){
  848. // Can't use signed ints, cause we'll lose range
  849. Vc->TokenRateChange = NewTokenRate - OldTokenRate;
  850. Vc->RemainingBandwidthIncreased = FALSE;
  851. }
  852. else{
  853. Vc->TokenRateChange = OldTokenRate - NewTokenRate;
  854. Vc->RemainingBandwidthIncreased = TRUE;
  855. }
  856. PS_UNLOCK( Lock );
  857. }
  858. }
  859. else{
  860. PS_UNLOCK(Lock);
  861. }
  862. }
  863. return Status;
  864. } // AcquireFlowResources
  865. VOID
  866. CancelAcquiredFlowResources(
  867. PGPC_CLIENT_VC Vc
  868. )
  869. /*++
  870. Routine Description:
  871. Called when a modify or add flwo failed, after we did admission control.
  872. Arguments:
  873. Vc - pointer to client vc's context block
  874. Return Value:
  875. None
  876. --*/
  877. {
  878. PADAPTER Adapter;
  879. PPS_SPIN_LOCK Lock;
  880. PULONG RemainingBandWidth;
  881. Adapter = Vc->Adapter;
  882. PsStructAssert(Adapter);
  883. if(Adapter->MediaType == NdisMediumWan && (!IsBestEffortVc(Vc)))
  884. {
  885. Lock = &Vc->WanLink->Lock;
  886. RemainingBandWidth = &Vc->WanLink->RemainingBandWidth;
  887. return;
  888. }
  889. else
  890. {
  891. Lock = &Adapter->Lock;
  892. RemainingBandWidth = &Adapter->RemainingBandWidth;
  893. }
  894. if(!Vc->TokenRateChange){
  895. return;
  896. }
  897. PS_LOCK( Lock );
  898. if(Vc->RemainingBandwidthIncreased){
  899. *RemainingBandWidth -= Vc->TokenRateChange;
  900. }
  901. else{
  902. *RemainingBandWidth += Vc->TokenRateChange;
  903. }
  904. //
  905. // Now that we have already returned the correct TokenRate, we need to set it to 0
  906. // so that this is not used in subsequent VC operations.
  907. //
  908. Vc->TokenRateChange = 0;
  909. // PsAssert(Adapter->RemainingBandWidth <= Adapter->NonBestEffortLimit);
  910. PS_UNLOCK( Lock );
  911. } // CancelAcquiredFlowResources
  912. VOID
  913. ReturnFlowResources(
  914. PGPC_CLIENT_VC Vc,
  915. PULONG RemainingBandWidthChanged
  916. )
  917. /*++
  918. Routine Description:
  919. Return all the resources acquired for this flow
  920. Arguments:
  921. Vc - pointer to client vc's context block
  922. Return Value:
  923. None
  924. --*/
  925. {
  926. PADAPTER Adapter;
  927. PCO_CALL_MANAGER_PARAMETERS CmParams = Vc->CallParameters->CallMgrParameters;
  928. ULONG TokenRate = CmParams->Transmit.TokenRate;
  929. SERVICETYPE ServiceType = CmParams->Transmit.ServiceType;
  930. PPS_SPIN_LOCK Lock;
  931. PULONG RemainingBandWidth;
  932. Adapter = Vc->Adapter;
  933. PsStructAssert(Adapter);
  934. *RemainingBandWidthChanged = FALSE;
  935. if(Adapter->MediaType == NdisMediumWan && (!IsBestEffortVc(Vc)))
  936. {
  937. RemainingBandWidth = &Vc->WanLink->RemainingBandWidth;
  938. Lock = &Vc->WanLink->Lock;
  939. return;
  940. }
  941. else
  942. {
  943. RemainingBandWidth = &Adapter->RemainingBandWidth;
  944. Lock = &Adapter->Lock;
  945. }
  946. if (ServiceType == SERVICETYPE_BESTEFFORT ||
  947. ServiceType == SERVICETYPE_NETWORK_CONTROL ||
  948. ServiceType == SERVICETYPE_QUALITATIVE)
  949. {
  950. return;
  951. }
  952. *RemainingBandWidthChanged = TRUE;
  953. PsAssert((LONG)TokenRate > 0);
  954. PS_LOCK( Lock );
  955. *RemainingBandWidth += TokenRate;
  956. // PsAssert(Adapter->RemainingBandWidth <= Adapter->NonBestEffortLimit);
  957. PS_UNLOCK( Lock );
  958. } // ReturnFlowResources
  959. NDIS_STATUS
  960. CreateBestEffortVc(
  961. PADAPTER Adapter,
  962. PGPC_CLIENT_VC Vc,
  963. PPS_WAN_LINK WanLink
  964. )
  965. {
  966. PCO_CALL_PARAMETERS CallParams;
  967. PCO_CALL_MANAGER_PARAMETERS CallMgrParameters;
  968. PCO_MEDIA_PARAMETERS MediaParameters;
  969. ULONG CallParamsLength;
  970. NDIS_STATUS Status;
  971. int i;
  972. InitGpcClientVc(Vc, GPC_CLIENT_BEST_EFFORT_VC, Adapter);
  973. SetLLTag(Vc, GpcClientVc);
  974. //
  975. // Invalidate all the port numbers
  976. for( i = 0; i < PORT_LIST_LEN; i++)
  977. {
  978. Vc->SrcPort[i] = 0xffff;
  979. Vc->DstPort[i] = 0xffff;
  980. }
  981. // Next Insertion will be at index 0
  982. Vc->NextSlot = 0;
  983. //
  984. // Allocate the resources for the call manager parameters.
  985. //
  986. CallParamsLength = sizeof(CO_CALL_PARAMETERS) +
  987. sizeof(CO_CALL_MANAGER_PARAMETERS) +
  988. sizeof(QOS_SD_MODE) +
  989. sizeof(QOS_OBJECT_HDR) +
  990. FIELD_OFFSET(CO_MEDIA_PARAMETERS, MediaSpecific) +
  991. FIELD_OFFSET(CO_SPECIFIC_PARAMETERS, Parameters);
  992. if(Adapter->MediaType == NdisMediumWan)
  993. {
  994. CallParamsLength += sizeof(QOS_WAN_MEDIA);
  995. Vc->PsPipeContext = WanLink->PsPipeContext;
  996. Vc->PsComponent = WanLink->PsComponent;
  997. Vc->AdapterStats = &WanLink->Stats;
  998. Vc->WanLink = WanLink;
  999. Vc->Flags |= GPC_WANLINK_VC;
  1000. if(Adapter->BestEffortLimit != UNSPECIFIED_RATE)
  1001. {
  1002. //
  1003. // If LBE is specified over WAN, use UBE
  1004. //
  1005. PsAdapterWriteEventLog(
  1006. EVENT_PS_WAN_LIMITED_BESTEFFORT,
  1007. 0,
  1008. &Adapter->MpDeviceName,
  1009. 0,
  1010. NULL);
  1011. Adapter->BestEffortLimit = UNSPECIFIED_RATE;
  1012. }
  1013. }
  1014. else
  1015. {
  1016. Vc->PsPipeContext = Adapter->PsPipeContext;
  1017. Vc->PsComponent = Adapter->PsComponent;
  1018. Vc->AdapterStats = &Adapter->Stats;
  1019. }
  1020. PsAllocatePool(CallParams, CallParamsLength, CmParamsTag);
  1021. if(CallParams == NULL)
  1022. {
  1023. return NDIS_STATUS_RESOURCES;
  1024. }
  1025. //
  1026. // build a call params struct describing the flow
  1027. //
  1028. NdisZeroMemory(CallParams, CallParamsLength);
  1029. //
  1030. // Build the Call Manager Parameters.
  1031. //
  1032. CallMgrParameters = (PCO_CALL_MANAGER_PARAMETERS)(CallParams + 1);
  1033. if(Adapter->BestEffortLimit == UNSPECIFIED_RATE)
  1034. {
  1035. FillInCmParams(CallMgrParameters,
  1036. SERVICETYPE_BESTEFFORT,
  1037. (ULONG)UNSPECIFIED_RATE,
  1038. (ULONG)UNSPECIFIED_RATE,
  1039. Adapter->TotalSize,
  1040. QOS_UNSPECIFIED,
  1041. QOS_UNSPECIFIED);
  1042. }
  1043. else
  1044. {
  1045. //
  1046. // Limited Best Effort
  1047. //
  1048. PsAssert(Adapter->MediaType != NdisMediumWan);
  1049. if(Adapter->BestEffortLimit >= Adapter->LinkSpeed) {
  1050. // If the specified limit is greater than the link speed,
  1051. // then we should operate in unlimited best-effort mode.
  1052. PsAdapterWriteEventLog(
  1053. EVENT_PS_BAD_BESTEFFORT_LIMIT,
  1054. 0,
  1055. &Adapter->MpDeviceName,
  1056. 0,
  1057. NULL);
  1058. PsDbgOut(DBG_INFO,
  1059. DBG_PROTOCOL,
  1060. ("[CreateBestEffortVc]: b/e limit %d exceeds link speed %d\n",
  1061. Adapter->BestEffortLimit,
  1062. Adapter->LinkSpeed));
  1063. Adapter->BestEffortLimit = UNSPECIFIED_RATE;
  1064. FillInCmParams(CallMgrParameters,
  1065. SERVICETYPE_BESTEFFORT,
  1066. (ULONG)UNSPECIFIED_RATE,
  1067. (ULONG)UNSPECIFIED_RATE,
  1068. Adapter->TotalSize,
  1069. QOS_UNSPECIFIED,
  1070. QOS_UNSPECIFIED);
  1071. }
  1072. else
  1073. {
  1074. FillInCmParams(CallMgrParameters,
  1075. SERVICETYPE_BESTEFFORT,
  1076. Adapter->BestEffortLimit,
  1077. (ULONG)UNSPECIFIED_RATE,
  1078. Adapter->TotalSize,
  1079. TC_NONCONF_SHAPE,
  1080. QOS_UNSPECIFIED);
  1081. }
  1082. }
  1083. //
  1084. // Build the MediaParameters.
  1085. //
  1086. CallParams->MediaParameters =
  1087. (PCO_MEDIA_PARAMETERS)(CallMgrParameters + 1);
  1088. MediaParameters = (PCO_MEDIA_PARAMETERS)((PUCHAR)
  1089. CallMgrParameters +
  1090. sizeof(CO_CALL_MANAGER_PARAMETERS) +
  1091. sizeof(QOS_SD_MODE) +
  1092. sizeof(QOS_OBJECT_HDR));
  1093. MediaParameters->Flags = 0;
  1094. MediaParameters->ReceivePriority = 0;
  1095. MediaParameters->ReceiveSizeHint = 0;
  1096. MediaParameters->MediaSpecific.ParamType = PARAM_TYPE_GQOS_INFO;
  1097. MediaParameters->MediaSpecific.Length = 0;
  1098. CallParams->Flags = 0;
  1099. CallParams->CallMgrParameters = CallMgrParameters;
  1100. CallParams->MediaParameters = (PCO_MEDIA_PARAMETERS)MediaParameters;
  1101. if(Adapter->MediaType == NdisMediumWan) {
  1102. LPQOS_WAN_MEDIA WanMedia;
  1103. MediaParameters->MediaSpecific.Length += sizeof(QOS_WAN_MEDIA);
  1104. WanMedia = (LPQOS_WAN_MEDIA) MediaParameters->MediaSpecific.Parameters;
  1105. NdisZeroMemory(WanMedia, sizeof(QOS_WAN_MEDIA));
  1106. WanMedia->ObjectHdr.ObjectType = QOS_OBJECT_WAN_MEDIA;
  1107. WanMedia->ObjectHdr.ObjectLength = sizeof(QOS_WAN_MEDIA);
  1108. NdisMoveMemory(&WanMedia->LinkId,
  1109. &WanLink->OriginalRemoteMacAddress,
  1110. 6);
  1111. }
  1112. Vc->CallParameters = CallParams;
  1113. Status = CmMakeCall(Vc);
  1114. PsAssert(Status != NDIS_STATUS_PENDING);
  1115. if(Status == NDIS_STATUS_SUCCESS)
  1116. {
  1117. REFADD(&Adapter->RefCount, 'ADVC');
  1118. if(Adapter->MediaType == NdisMediumWan)
  1119. {
  1120. REFADD(&WanLink->RefCount, 'WANV');
  1121. }
  1122. //
  1123. // Also save the non conforming value - so that the sequencer can stamp it
  1124. // for non conforming packets. This will not change between reboots & hence
  1125. // need not be done in the ModifyCfInfo
  1126. //
  1127. Vc->UserPriorityNonConforming = Adapter->UserServiceTypeNonConforming;
  1128. switch(Vc->CallParameters->CallMgrParameters->Transmit.ServiceType)
  1129. {
  1130. case SERVICETYPE_CONTROLLEDLOAD:
  1131. Vc->UserPriorityConforming = Adapter->UserServiceTypeControlledLoad;
  1132. Vc->IPPrecedenceNonConforming = Adapter->IPServiceTypeControlledLoadNC;
  1133. break;
  1134. case SERVICETYPE_GUARANTEED:
  1135. Vc->UserPriorityConforming = Adapter->UserServiceTypeGuaranteed;
  1136. Vc->IPPrecedenceNonConforming = Adapter->IPServiceTypeGuaranteedNC;
  1137. break;
  1138. case SERVICETYPE_BESTEFFORT:
  1139. Vc->UserPriorityConforming = Adapter->UserServiceTypeBestEffort;
  1140. Vc->IPPrecedenceNonConforming = Adapter->IPServiceTypeBestEffortNC;
  1141. break;
  1142. case SERVICETYPE_QUALITATIVE:
  1143. Vc->UserPriorityConforming = Adapter->UserServiceTypeQualitative;
  1144. Vc->IPPrecedenceNonConforming = Adapter->IPServiceTypeQualitativeNC;
  1145. break;
  1146. case SERVICETYPE_NETWORK_CONTROL:
  1147. Vc->UserPriorityConforming = Adapter->UserServiceTypeNetworkControl;
  1148. Vc->IPPrecedenceNonConforming = Adapter->IPServiceTypeNetworkControlNC;
  1149. break;
  1150. }
  1151. //
  1152. // Transistion to the Call complete state
  1153. //
  1154. CallSucceededStateTransition(Vc);
  1155. }
  1156. return Status;
  1157. }
  1158. NDIS_STATUS
  1159. RemoveDiffservMapping(
  1160. PGPC_CLIENT_VC Vc
  1161. )
  1162. {
  1163. LPQOS_OBJECT_HDR QoSObject;
  1164. ULONG ParamsLength;
  1165. ULONG DSFieldCount;
  1166. LPQOS_DIFFSERV_RULE pDiffServRule;
  1167. ULONG i;
  1168. PADAPTER Adapter = Vc->Adapter;
  1169. PCO_CALL_MANAGER_PARAMETERS CallParameters = Vc->CallParameters->CallMgrParameters;
  1170. PDIFFSERV_MAPPING pDiffServMapping;
  1171. ParamsLength = (LONG)CallParameters->CallMgrSpecific.Length;
  1172. QoSObject = (LPQOS_OBJECT_HDR)CallParameters->CallMgrSpecific.Parameters;
  1173. while(ParamsLength > 0) {
  1174. if(QoSObject->ObjectType == QOS_OBJECT_DIFFSERV)
  1175. {
  1176. DSFieldCount = (((LPQOS_DIFFSERV)QoSObject)->DSFieldCount);
  1177. //
  1178. // Make sure that everything that we are clearing is mapped to the same Vc.
  1179. //
  1180. PS_LOCK(&Adapter->Lock);
  1181. if(Vc->WanLink)
  1182. {
  1183. pDiffServMapping = Vc->WanLink->pDiffServMapping;
  1184. }
  1185. else
  1186. {
  1187. pDiffServMapping = Vc->Adapter->pDiffServMapping;
  1188. }
  1189. for(i=0, pDiffServRule = ((LPQOS_DIFFSERV_RULE)((LPQOS_DIFFSERV)QoSObject)->DiffservRule);
  1190. i<DSFieldCount;
  1191. i++, pDiffServRule++)
  1192. {
  1193. UCHAR tos = pDiffServRule->InboundDSField;
  1194. if(pDiffServMapping[tos].Vc == Vc) {
  1195. pDiffServMapping[tos].Vc = 0;
  1196. }
  1197. else
  1198. {
  1199. //
  1200. // We are trying to remove a codepoint that is mapped to another VC. Ideally, this
  1201. // should never happen. We still need to check that this is a valid VC (otherwise, if
  1202. // a diffserv rule has the same codepoint more than one time, we could still hit this
  1203. // assert, because the first codepoint will clear the mapping and the second codepoint
  1204. // will see the NULL - so we check if the Vc is non null)
  1205. //
  1206. if(pDiffServMapping[tos].Vc)
  1207. {
  1208. PsDbgOut(DBG_FAILURE, DBG_VC,
  1209. ("[RemoveDiffservMapping]: Vc %08X, Trying to remove codepoint %d that "
  1210. "is mapped to Vc %08X \n",
  1211. Vc,
  1212. pDiffServRule->InboundDSField,
  1213. pDiffServMapping[pDiffServRule->InboundDSField].Vc));
  1214. PsAssert(0);
  1215. }
  1216. }
  1217. }
  1218. #if DBG
  1219. //
  1220. // Make sure that no TOS mapping points to this VC.
  1221. //
  1222. for(i=0; i<=PREC_MAX_VALUE; i++) {
  1223. PsAssert(pDiffServMapping[i].Vc != Vc);
  1224. }
  1225. #endif
  1226. PS_UNLOCK(&Adapter->Lock);
  1227. return NDIS_STATUS_SUCCESS;
  1228. }
  1229. ParamsLength -= QoSObject->ObjectLength;
  1230. QoSObject = (LPQOS_OBJECT_HDR)((UINT_PTR)QoSObject +
  1231. QoSObject->ObjectLength);
  1232. }
  1233. return NDIS_STATUS_SUCCESS;
  1234. }
  1235. NDIS_STATUS
  1236. ProcessDiffservFlow(
  1237. PGPC_CLIENT_VC Vc,
  1238. PCO_CALL_MANAGER_PARAMETERS CallParameters)
  1239. {
  1240. LPQOS_OBJECT_HDR QoSObject;
  1241. ULONG ParamsLength;
  1242. ULONG DSFieldCount;
  1243. LPQOS_DIFFSERV_RULE pDiffServRule;
  1244. ULONG i;
  1245. PGPC_CLIENT_VC CurrentVc;
  1246. PADAPTER Adapter = Vc->Adapter;
  1247. PDIFFSERV_MAPPING pDiffServMapping;
  1248. PDIFFSERV_MAPPING *pD;
  1249. ParamsLength = (LONG)CallParameters->CallMgrSpecific.Length;
  1250. QoSObject = (LPQOS_OBJECT_HDR)CallParameters->CallMgrSpecific.Parameters;
  1251. while(ParamsLength > 0)
  1252. {
  1253. if(QoSObject->ObjectType == QOS_OBJECT_DIFFSERV)
  1254. {
  1255. //
  1256. // We have found the diffserv QoS object. This could be due to a add or modify of
  1257. // the flow. If this is an add, we are okay. If it is a modify, there are 2 cases.
  1258. // 1. Modify from an RSVP flow to a Diffserv Flow.
  1259. // 2. Modify from a diffserv flow to another diffserv flow.
  1260. //
  1261. DSFieldCount = (((LPQOS_DIFFSERV)QoSObject)->DSFieldCount);
  1262. PS_LOCK(&Adapter->Lock);
  1263. if(Vc->WanLink)
  1264. {
  1265. pDiffServMapping = Vc->WanLink->pDiffServMapping;
  1266. pD = &Vc->WanLink->pDiffServMapping;
  1267. }
  1268. else
  1269. {
  1270. pDiffServMapping = Vc->Adapter->pDiffServMapping;
  1271. pD = &Vc->Adapter->pDiffServMapping;
  1272. }
  1273. if(pDiffServMapping == 0)
  1274. {
  1275. //
  1276. // To optimize on memory, we allocate the diffserv mapping only when someone creates
  1277. // a Diffserv flow on that adapter or wanlink.
  1278. //
  1279. // We could further optimize this by freeing this when the last diffserv flow went
  1280. // away - For now, we assume that if a Diffserv flow is created on an interface, then the
  1281. // interface is probably going to be used for Diffserv mode till the next reboot. This is
  1282. // not such a bad assumption, because the Diffserv mode is meaningful only on routers
  1283. // and we don't expect to switch b/w these modes very often.
  1284. //
  1285. PsAllocatePool(*pD,
  1286. sizeof(DIFFSERV_MAPPING) * (PREC_MAX_VALUE+1),
  1287. PsMiscTag);
  1288. if(*pD == 0)
  1289. {
  1290. PS_UNLOCK(&Adapter->Lock);
  1291. return NDIS_STATUS_RESOURCES;
  1292. }
  1293. else
  1294. {
  1295. NdisZeroMemory(*pD, sizeof(DIFFSERV_MAPPING) * (PREC_MAX_VALUE+1));
  1296. }
  1297. pDiffServMapping = *pD;
  1298. }
  1299. //
  1300. // Make sure that everything is either unmapped, or is mapped to the same vc (for modify)
  1301. //
  1302. for(i=0, pDiffServRule = ((LPQOS_DIFFSERV_RULE)((LPQOS_DIFFSERV)QoSObject)->DiffservRule);
  1303. i<DSFieldCount;
  1304. i++, pDiffServRule++)
  1305. {
  1306. uchar tos = pDiffServRule->InboundDSField;
  1307. CurrentVc = pDiffServMapping[tos].Vc;
  1308. if(CurrentVc) {
  1309. if(CurrentVc != Vc) {
  1310. PS_UNLOCK(&Adapter->Lock);
  1311. PsDbgOut(DBG_FAILURE, DBG_GPC_QOS,
  1312. ("[ProcessDiffservFlow]: Adapter %08X, Vc%08X: CodePoint %d already "
  1313. " mapped to Vc 0x%x \n",
  1314. Adapter,
  1315. Vc,
  1316. pDiffServRule->InboundDSField,
  1317. CurrentVc));
  1318. return QOS_STATUS_DS_MAPPING_EXISTS;
  1319. }
  1320. PsAssert(Vc->ModifyCallParameters);
  1321. }
  1322. }
  1323. if(Vc->ModifyCallParameters) {
  1324. //
  1325. // for a modify, we need to unmap the ones that are not there in this rule
  1326. //
  1327. for(i=0; i<=PREC_MAX_VALUE; i++) {
  1328. if(pDiffServMapping[i].Vc == Vc) {
  1329. pDiffServMapping[i].Vc = 0;
  1330. }
  1331. }
  1332. }
  1333. //
  1334. // Map (or re-map)
  1335. //
  1336. for(i=0, pDiffServRule = ((LPQOS_DIFFSERV_RULE)((LPQOS_DIFFSERV)QoSObject)->DiffservRule);
  1337. i<DSFieldCount;
  1338. i++, pDiffServRule++)
  1339. {
  1340. uchar tos = pDiffServRule->InboundDSField;
  1341. pDiffServMapping[tos].Vc = Vc;
  1342. pDiffServMapping[tos].ConformingOutboundDSField =
  1343. pDiffServRule->ConformingOutboundDSField << 2;
  1344. pDiffServMapping[tos].NonConformingOutboundDSField =
  1345. pDiffServRule->NonConformingOutboundDSField << 2;
  1346. pDiffServMapping[tos].ConformingUserPriority =
  1347. pDiffServRule->ConformingUserPriority;
  1348. pDiffServMapping[tos].NonConformingUserPriority =
  1349. pDiffServRule->NonConformingUserPriority;
  1350. }
  1351. PS_UNLOCK(&Adapter->Lock);
  1352. return NDIS_STATUS_SUCCESS;
  1353. }
  1354. ParamsLength -= QoSObject->ObjectLength;
  1355. QoSObject = (LPQOS_OBJECT_HDR)((UINT_PTR)QoSObject +
  1356. QoSObject->ObjectLength);
  1357. }
  1358. //
  1359. // This is a RSVP flow. If this is a modify, we need to unmap existing diffserv flows, because
  1360. // we could be changing this from a Diffserv Flow to a RSVP flow.
  1361. //
  1362. if(Vc->ModifyCallParameters)
  1363. {
  1364. //
  1365. // for a modify, we need to unmap the ones that are not there in this rule
  1366. //
  1367. PS_LOCK(&Adapter->Lock);
  1368. if(Vc->WanLink)
  1369. {
  1370. pDiffServMapping = Vc->WanLink->pDiffServMapping;
  1371. }
  1372. else
  1373. {
  1374. pDiffServMapping = Vc->Adapter->pDiffServMapping;
  1375. }
  1376. if(pDiffServMapping)
  1377. {
  1378. for(i=0; i<=PREC_MAX_VALUE; i++)
  1379. {
  1380. if(pDiffServMapping[i].Vc == Vc)
  1381. {
  1382. pDiffServMapping[i].Vc = 0;
  1383. }
  1384. }
  1385. }
  1386. PS_UNLOCK(&Adapter->Lock);
  1387. }
  1388. return NDIS_STATUS_SUCCESS;
  1389. }
  1390. /* end cmvc.c */