Leaked source code of windows server 2003
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.

1523 lines
40 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. ValidateCallParameters(
  20. PGPC_CLIENT_VC Vc,
  21. PCO_CALL_MANAGER_PARAMETERS CallParameters
  22. );
  23. NDIS_STATUS
  24. AcquireFlowResources(
  25. PGPC_CLIENT_VC Vc,
  26. PCO_CALL_MANAGER_PARAMETERS NewCallParams,
  27. PCO_CALL_MANAGER_PARAMETERS OldCallParams,
  28. PULONG RemainingBandWidthChanged
  29. );
  30. VOID
  31. ReturnFlowResources(
  32. PGPC_CLIENT_VC Vc,
  33. PULONG RemainingBandWidthChanged
  34. );
  35. VOID
  36. CancelAcquiredFlowResources(
  37. PGPC_CLIENT_VC Vc
  38. );
  39. /* End Forward */
  40. NDIS_STATUS
  41. CmCreateVc(PGPC_CLIENT_VC *GpcClientVc,
  42. PADAPTER Adapter,
  43. PPS_WAN_LINK WanLink,
  44. PCO_CALL_PARAMETERS CallParams,
  45. GPC_HANDLE GpcCfInfoHandle,
  46. PCF_INFO_QOS CfInfoPtr,
  47. GPC_CLIENT_HANDLE ClientContext)
  48. {
  49. PGPC_CLIENT_VC Vc;
  50. *GpcClientVc = NULL;
  51. PsAllocFromLL(&Vc, &GpcClientVcLL, GpcClientVc);
  52. if(Vc == NULL)
  53. {
  54. return NDIS_STATUS_RESOURCES;
  55. }
  56. InitGpcClientVc(Vc, 0, Adapter);
  57. SetLLTag(Vc, GpcClientVc);
  58. //
  59. // Allocate space for the instance name for the Vc.
  60. //
  61. PsAllocatePool(Vc->InstanceName.Buffer,
  62. Adapter->WMIInstanceName.Length + VcPrefix.Length + INSTANCE_ID_SIZE,
  63. PsMiscTag);
  64. if(!Vc->InstanceName.Buffer)
  65. {
  66. PsFreeToLL(Vc, &GpcClientVcLL, GpcClientVc);
  67. return NDIS_STATUS_RESOURCES;
  68. }
  69. Vc->CfInfoHandle = GpcCfInfoHandle;
  70. Vc->CfType = ClientContext;
  71. Vc->CfInfoQoS = CfInfoPtr;
  72. Vc->CallParameters = CallParams;
  73. PS_LOCK(&Adapter->Lock);
  74. if(Adapter->PsMpState == AdapterStateRunning)
  75. {
  76. //
  77. // Insert the Vc in the adapter list
  78. //
  79. InsertHeadList(&Adapter->GpcClientVcList, &Vc->Linkage);
  80. PS_UNLOCK(&Adapter->Lock);
  81. }
  82. else
  83. {
  84. PsFreePool(Vc->InstanceName.Buffer);
  85. PsFreeToLL(Vc, &GpcClientVcLL, GpcClientVc);
  86. PS_UNLOCK(&Adapter->Lock);
  87. return GPC_STATUS_NOTREADY;
  88. }
  89. if(WanLink) {
  90. Vc->Flags |= GPC_WANLINK_VC;
  91. //
  92. // We need to link the VC to the WanLink. This has to be done because
  93. // we have to clean up when we get a NDIS_STATUS_WAN_LINE_DOWN
  94. //
  95. Vc->AdapterStats = &WanLink->Stats;
  96. Vc->WanLink = WanLink;
  97. Vc->PsPipeContext = WanLink->PsPipeContext;
  98. Vc->PsComponent = WanLink->PsComponent;
  99. }
  100. else
  101. {
  102. Vc->AdapterStats = &Adapter->Stats;
  103. Vc->PsPipeContext = Adapter->PsPipeContext;
  104. Vc->PsComponent = Adapter->PsComponent;
  105. }
  106. *GpcClientVc = Vc;
  107. return NDIS_STATUS_SUCCESS;
  108. } // CmCreateVc
  109. BOOLEAN
  110. IsIsslowFlow(
  111. IN PGPC_CLIENT_VC Vc,
  112. IN PCO_CALL_PARAMETERS CallParameters
  113. )
  114. {
  115. LONG ParamsLength;
  116. LPQOS_OBJECT_HDR QoSObject;
  117. PADAPTER Adapter = Vc->Adapter;
  118. PCO_MEDIA_PARAMETERS CallMgrParams = CallParameters->MediaParameters;
  119. ULONGLONG i,j,k;
  120. ParamsLength = (LONG)CallMgrParams->MediaSpecific.Length;
  121. QoSObject = (LPQOS_OBJECT_HDR)CallMgrParams->MediaSpecific.Parameters;
  122. while(ParamsLength > 0)
  123. {
  124. if(QoSObject->ObjectType == QOS_OBJECT_WAN_MEDIA)
  125. {
  126. if((Vc->WanLink->LinkSpeed <= Adapter->ISSLOWLinkSpeed) &&
  127. (CallParameters->CallMgrParameters->Transmit.ServiceType != SERVICETYPE_BESTEFFORT))
  128. {
  129. i = (ULONGLONG) Adapter->ISSLOWTokenRate * (ULONGLONG) CallParameters->CallMgrParameters->Transmit.MaxSduSize;
  130. j = (ULONGLONG) Adapter->ISSLOWPacketSize * (ULONGLONG) CallParameters->CallMgrParameters->Transmit.TokenRate;
  131. k = (ULONGLONG) Adapter->ISSLOWTokenRate * (ULONGLONG)Adapter->ISSLOWPacketSize;
  132. if((i+j)<k)
  133. return TRUE;
  134. }
  135. return FALSE;
  136. }
  137. else
  138. {
  139. if( ((LONG)QoSObject->ObjectLength <= 0) ||
  140. ((LONG)QoSObject->ObjectLength > ParamsLength) )
  141. {
  142. return(FALSE);
  143. }
  144. ParamsLength -= QoSObject->ObjectLength;
  145. QoSObject = (LPQOS_OBJECT_HDR)((UINT_PTR)QoSObject + QoSObject->ObjectLength);
  146. }
  147. }
  148. return FALSE;
  149. }
  150. NDIS_STATUS
  151. CmMakeCall(
  152. IN PGPC_CLIENT_VC Vc
  153. )
  154. {
  155. ULONG CmParamsLength;
  156. NDIS_STATUS Status;
  157. ULONG RemainingBandWidthChanged;
  158. PADAPTER Adapter = Vc->Adapter;
  159. PCO_CALL_PARAMETERS CallParameters = Vc->CallParameters;
  160. //
  161. // Validate parameters
  162. //
  163. Status = ValidateCallParameters(Vc, CallParameters->CallMgrParameters);
  164. if(Status != NDIS_STATUS_SUCCESS)
  165. {
  166. PsDbgOut(DBG_INFO,
  167. DBG_VC,
  168. ("[CmMakeCall]: Vc %08X, invalid QoS parameters\n",
  169. Vc));
  170. return Status;
  171. }
  172. //
  173. // make sure we can admit the flow onto our adapter. if this
  174. // succeeds, the resources are committed and we'll have to call
  175. // CancelAcquiredFlowResources to return them.
  176. //
  177. Status = AcquireFlowResources(Vc,
  178. CallParameters->CallMgrParameters,
  179. NULL,
  180. &RemainingBandWidthChanged);
  181. if(Status != NDIS_STATUS_SUCCESS)
  182. {
  183. PsDbgOut(DBG_INFO,
  184. DBG_VC,
  185. ("[CmMakeCall]: Vc %08X, no flow resc\n",
  186. Vc));
  187. return Status;
  188. }
  189. //
  190. // In the integrated call manager/miniport model, the activation
  191. // is internal. Activating the Vc consists of adding the flow to the
  192. // scheduler. If it succeeds, we will later call NdisMCmActivateVc,
  193. // just as a courtesy, to notify NDIS.
  194. //
  195. if( Adapter->MediaType == NdisMediumWan &&
  196. !IsBestEffortVc(Vc) &&
  197. IsIsslowFlow( Vc, CallParameters ) )
  198. {
  199. // Need to do this before we add a flow to the sched components.
  200. Vc->Flags |= GPC_ISSLOW_FLOW;
  201. }
  202. Status = AddFlowToScheduler(NEW_VC, Vc, CallParameters, 0);
  203. // Let's revert it back, to avoid any side effects..
  204. Vc->Flags = Vc->Flags & ~GPC_ISSLOW_FLOW;
  205. if(Status != NDIS_STATUS_SUCCESS)
  206. {
  207. PsDbgOut(DBG_FAILURE,
  208. DBG_VC,
  209. ("[CmMakeCall]: Vc %08X, AddFlowToScheduler failed %08X\n",
  210. Vc,
  211. Status));
  212. CancelAcquiredFlowResources(Vc);
  213. return(Status);
  214. }
  215. //
  216. // A flow has been added to psched after this point. So, whenever the Vc goes away, Psched's flow
  217. // has to be removed from an explicit call.
  218. //
  219. Vc->bRemoveFlow = TRUE;
  220. //
  221. // If there is an NDIS 5.0, connection oriented driver below us, then
  222. // we need to call it, with the call parameters, to complete the VC
  223. // setup.
  224. //
  225. if(Adapter->MediaType == NdisMediumWan &&
  226. !IsBestEffortVc(Vc))
  227. {
  228. Status = WanMakeCall(Vc, CallParameters);
  229. PsAssert(Status == NDIS_STATUS_PENDING);
  230. return Status;
  231. }
  232. else
  233. {
  234. if(TRUE == RemainingBandWidthChanged)
  235. {
  236. LONG RemainingBandWidth;
  237. PS_LOCK(&Adapter->Lock);
  238. RemainingBandWidth = (LONG) Adapter->RemainingBandWidth;
  239. PS_UNLOCK(&Adapter->Lock);
  240. PsTcNotify(Adapter, 0, OID_QOS_REMAINING_BANDWIDTH, &RemainingBandWidth, sizeof(LONG));
  241. }
  242. Vc->TokenRateChange = 0;
  243. return NDIS_STATUS_SUCCESS;
  244. }
  245. }
  246. VOID
  247. CompleteMakeCall(
  248. PGPC_CLIENT_VC Vc,
  249. PCO_CALL_PARAMETERS CallParameters,
  250. NDIS_STATUS Status
  251. )
  252. {
  253. PADAPTER Adapter = Vc->Adapter;
  254. PsAssert(Adapter->MediaType == NdisMediumWan);
  255. PsAssert(!IsBestEffortVc(Vc));
  256. if(Status != NDIS_STATUS_SUCCESS)
  257. {
  258. CancelAcquiredFlowResources(Vc);
  259. }
  260. Vc->TokenRateChange = 0;
  261. CmMakeCallComplete(Status, Vc, CallParameters);
  262. }
  263. NDIS_STATUS
  264. CmModifyCall(
  265. IN PGPC_CLIENT_VC Vc
  266. )
  267. /*++
  268. Routine Description:
  269. Modify the QoS of an existing flow based on the supplied call params.
  270. First see if the request can be handled locally.
  271. Arguments:
  272. See the DDK...
  273. Return Values:
  274. NDIS_STATUS_SUCCESS if everything worked ok.
  275. --*/
  276. {
  277. NDIS_STATUS Status;
  278. ULONG CmParamsLength;
  279. PCO_CALL_PARAMETERS CallParameters;
  280. PADAPTER Adapter;
  281. ULONG RemainingBandWidthChanged;
  282. Adapter = Vc->Adapter;
  283. PsStructAssert(Adapter);
  284. PsAssert(Vc->TokenRateChange == 0);
  285. //
  286. // Validate parameters
  287. //
  288. CallParameters = Vc->ModifyCallParameters;
  289. Status = ValidateCallParameters(Vc, CallParameters->CallMgrParameters);
  290. if(Status != NDIS_STATUS_SUCCESS)
  291. {
  292. PsDbgOut(DBG_INFO,
  293. DBG_VC,
  294. ("[CmModifyCallQoS]: Vc %08X, invalid QoS parameters\n",
  295. Vc));
  296. return Status;
  297. }
  298. //
  299. // make sure we can admit the flow onto our adapter. if this
  300. // succeeds, the resources are committed and we'll have to call
  301. // CancelAcquiredFlowResources to return them.
  302. //
  303. Status = AcquireFlowResources(Vc,
  304. CallParameters->CallMgrParameters,
  305. Vc->CallParameters->CallMgrParameters,
  306. &RemainingBandWidthChanged);
  307. if(Status != NDIS_STATUS_SUCCESS){
  308. PsDbgOut(DBG_INFO,
  309. DBG_VC,
  310. ("[CmModifyCallQoS]: Vc %08X, no flow resc\n",
  311. Vc));
  312. return Status;
  313. }
  314. Status = AddFlowToScheduler(MODIFY_VC, Vc, CallParameters, Vc->CallParameters);
  315. if(Status != NDIS_STATUS_SUCCESS){
  316. PsDbgOut(DBG_FAILURE,
  317. DBG_VC,
  318. ("[CmModifyCallQoS]: Vc %08X, failed %08X\n",
  319. Vc,
  320. Status));
  321. //
  322. // Free the copy we made, Cancel the committed resources.
  323. //
  324. CancelAcquiredFlowResources(Vc);
  325. return(Status);
  326. }
  327. //
  328. // If there is an NDIS 5.0, connection oriented driver below us, then
  329. // we need to call it, with the call parameters, to complete the VC
  330. // setup.
  331. //
  332. if(Adapter->MediaType == NdisMediumWan){
  333. Status = WanModifyCall(Vc, CallParameters);
  334. PsAssert(Status == NDIS_STATUS_PENDING);
  335. return(Status);
  336. }
  337. else
  338. {
  339. if(TRUE == RemainingBandWidthChanged) {
  340. LONG RemainingBandWidth;
  341. PS_LOCK(&Adapter->Lock);
  342. RemainingBandWidth = (LONG) Adapter->RemainingBandWidth;
  343. PS_UNLOCK(&Adapter->Lock);
  344. PsTcNotify(Adapter, 0, OID_QOS_REMAINING_BANDWIDTH, &RemainingBandWidth, sizeof(LONG));
  345. }
  346. Vc->TokenRateChange = 0;
  347. return(NDIS_STATUS_SUCCESS);
  348. }
  349. } // CmModifyCallQoS
  350. VOID
  351. ModifyCallComplete(
  352. PGPC_CLIENT_VC Vc,
  353. PCO_CALL_PARAMETERS CallParameters,
  354. NDIS_STATUS Status
  355. )
  356. {
  357. PADAPTER Adapter = Vc->Adapter;
  358. PsAssert(Adapter->MediaType == NdisMediumWan);
  359. PsAssert(!IsBestEffortVc(Vc));
  360. if(Status != NDIS_STATUS_SUCCESS) {
  361. //
  362. // Undo the add flow done above, by reversing the new and old parameters.
  363. //
  364. ValidateCallParameters(Vc, Vc->CallParameters->CallMgrParameters);
  365. Status = AddFlowToScheduler(MODIFY_VC, Vc, Vc->CallParameters, CallParameters);
  366. CancelAcquiredFlowResources(Vc);
  367. }
  368. Vc->TokenRateChange = 0;
  369. CmModifyCallComplete(Status, Vc, CallParameters);
  370. }
  371. NDIS_STATUS
  372. CmCloseCall(
  373. PGPC_CLIENT_VC Vc
  374. )
  375. {
  376. NDIS_STATUS Status;
  377. PADAPTER Adapter = Vc->Adapter;
  378. ULONG RemainingBandWidthChanged;
  379. PsStructAssert(Adapter);
  380. //
  381. // Here, we used to call RemoveFlowFromScheduler, which used to call "DeleteFlow". Instead, we will
  382. // call a new interface "EmptyPacketsFromScheduler", which will call "EmptyFlow" to empty all the
  383. // packets queued up in each of the components corresponding to this flow.
  384. //
  385. EmptyPacketsFromScheduler( Vc );
  386. ReturnFlowResources(Vc, &RemainingBandWidthChanged);
  387. if(TRUE == RemainingBandWidthChanged) {
  388. LONG RemainingBandWidth;
  389. PS_LOCK(&Adapter->Lock);
  390. RemainingBandWidth = (LONG) Adapter->RemainingBandWidth;
  391. PS_UNLOCK(&Adapter->Lock);
  392. PsTcNotify(Adapter, 0, OID_QOS_REMAINING_BANDWIDTH, &RemainingBandWidth, sizeof(LONG));
  393. }
  394. if(!IsBestEffortVc(Vc))
  395. {
  396. CmCloseCallComplete(NDIS_STATUS_SUCCESS, Vc);
  397. }
  398. else
  399. {
  400. DerefClVc(Vc);
  401. }
  402. return NDIS_STATUS_PENDING;
  403. }
  404. NDIS_STATUS
  405. CmDeleteVc(
  406. IN PGPC_CLIENT_VC Vc
  407. )
  408. {
  409. PsAssert(Vc->RefCount == 0);
  410. if(Vc->InstanceName.Buffer) {
  411. PsFreePool(Vc->InstanceName.Buffer);
  412. }
  413. if( Vc->bRemoveFlow)
  414. {
  415. Vc->bRemoveFlow = FALSE;
  416. RemoveFlowFromScheduler(Vc);
  417. }
  418. if(Vc->PsFlowContext) {
  419. if(Vc->Adapter->MediaType == NdisMediumWan) {
  420. if(Vc->PsFlowContext != Vc->WanLink->BestEffortVc.PsFlowContext) {
  421. PsFreePool(Vc->PsFlowContext);
  422. }
  423. else {
  424. if(Vc == &Vc->WanLink->BestEffortVc) {
  425. PsFreePool(Vc->PsFlowContext);
  426. }
  427. }
  428. }
  429. else {
  430. if(Vc->PsFlowContext != Vc->Adapter->BestEffortVc.PsFlowContext) {
  431. PsFreePool(Vc->PsFlowContext);
  432. }
  433. else {
  434. if(Vc == &Vc->Adapter->BestEffortVc) {
  435. PsFreePool(Vc->PsFlowContext);
  436. }
  437. }
  438. }
  439. }
  440. NdisFreeSpinLock(&Vc->Lock);
  441. NdisFreeSpinLock(&Vc->BytesScheduledLock);
  442. NdisFreeSpinLock(&Vc->BytesTransmittedLock);
  443. if(Vc->CallParameters){
  444. PsFreePool(Vc->CallParameters);
  445. Vc->CallParameters = NULL;
  446. }
  447. if(!IsBestEffortVc(Vc))
  448. {
  449. PS_LOCK(&Vc->Adapter->Lock);
  450. RemoveEntryList(&Vc->Linkage);
  451. PS_UNLOCK(&Vc->Adapter->Lock);
  452. if(Vc->Flags & GPC_WANLINK_VC)
  453. {
  454. REFDEL(&Vc->WanLink->RefCount, FALSE, 'WANV');
  455. }
  456. REFDEL(&Vc->Adapter->RefCount, FALSE, 'ADVC');
  457. PsFreeToLL(Vc, &GpcClientVcLL, GpcClientVc);
  458. }
  459. else
  460. {
  461. PADAPTER Adapter = Vc->Adapter;
  462. if(Vc->Flags & GPC_WANLINK_VC)
  463. {
  464. REFDEL(&Vc->WanLink->RefCount, FALSE, 'WANV');
  465. }
  466. REFDEL(&Adapter->RefCount, FALSE, 'ADVC');
  467. }
  468. return(NDIS_STATUS_SUCCESS);
  469. } // CmDeleteVc
  470. VOID
  471. FillInCmParams(
  472. PCO_CALL_MANAGER_PARAMETERS CmParams,
  473. SERVICETYPE ServiceType,
  474. ULONG TokenRate,
  475. ULONG PeakBandwidth,
  476. ULONG TokenBucketSize,
  477. ULONG DSMode,
  478. ULONG Priority)
  479. {
  480. PCO_SPECIFIC_PARAMETERS SpecificParameters;
  481. QOS_SD_MODE * QoSObjectSDMode;
  482. QOS_PRIORITY * QoSObjectPriority;
  483. QOS_OBJECT_HDR * QoSObjectHdr;
  484. CmParams->Transmit.ServiceType = ServiceType;
  485. CmParams->Transmit.TokenRate = TokenRate;
  486. CmParams->Transmit.PeakBandwidth = PeakBandwidth;
  487. CmParams->Transmit.TokenBucketSize = TokenBucketSize;
  488. CmParams->CallMgrSpecific.ParamType = PARAM_TYPE_GQOS_INFO;
  489. CmParams->CallMgrSpecific.Length = 0;
  490. SpecificParameters =
  491. (PCO_SPECIFIC_PARAMETERS)&CmParams->CallMgrSpecific.Parameters;
  492. if(DSMode != QOS_UNSPECIFIED){
  493. CmParams->CallMgrSpecific.Length += sizeof(QOS_SD_MODE);
  494. QoSObjectSDMode = (QOS_SD_MODE *)SpecificParameters;
  495. QoSObjectSDMode->ObjectHdr.ObjectType = QOS_OBJECT_SD_MODE;
  496. QoSObjectSDMode->ObjectHdr.ObjectLength = sizeof(QOS_SD_MODE);
  497. QoSObjectSDMode->ShapeDiscardMode = DSMode;
  498. (QOS_SD_MODE *)SpecificParameters++;
  499. }
  500. if(Priority != QOS_UNSPECIFIED){
  501. CmParams->CallMgrSpecific.Length += sizeof(QOS_PRIORITY);
  502. QoSObjectPriority = (QOS_PRIORITY *)SpecificParameters;
  503. QoSObjectPriority->ObjectHdr.ObjectType = QOS_OBJECT_PRIORITY;
  504. QoSObjectPriority->ObjectHdr.ObjectLength = sizeof(QOS_PRIORITY);
  505. QoSObjectPriority->SendPriority = (UCHAR)Priority;
  506. (QOS_PRIORITY *)SpecificParameters++;
  507. }
  508. QoSObjectHdr = (QOS_OBJECT_HDR *)SpecificParameters;
  509. QoSObjectHdr->ObjectType = QOS_OBJECT_END_OF_LIST;
  510. QoSObjectHdr->ObjectLength = sizeof(QOS_OBJECT_HDR);
  511. }
  512. NDIS_STATUS
  513. ValidateCallParameters(
  514. PGPC_CLIENT_VC Vc,
  515. PCO_CALL_MANAGER_PARAMETERS CallParameters
  516. )
  517. {
  518. ULONG TokenRate = CallParameters->Transmit.TokenRate;
  519. SERVICETYPE ServiceType = CallParameters->Transmit.ServiceType;
  520. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  521. UCHAR SendPriority;
  522. ULONG SDMode;
  523. ULONG PeakBandwidth;
  524. LONG ParamsLength;
  525. LPQOS_OBJECT_HDR QoSObject;
  526. ULONG Class;
  527. ULONG DSFieldCount;
  528. LPQOS_DIFFSERV_RULE pDiffServRule;
  529. ULONG i;
  530. ULONG ShapingRate;
  531. ParamsLength = (LONG)CallParameters->CallMgrSpecific.Length;
  532. PeakBandwidth = CallParameters->Transmit.PeakBandwidth;
  533. //
  534. // By default, we want to shape to the TokenRate
  535. //
  536. Vc->ShapeTokenRate = TokenRate;
  537. QoSObject = (LPQOS_OBJECT_HDR)CallParameters->CallMgrSpecific.Parameters;
  538. while (ParamsLength > sizeof(QOS_OBJECT_HDR)) {
  539. switch(QoSObject->ObjectType){
  540. case QOS_OBJECT_TRAFFIC_CLASS:
  541. if (ParamsLength < sizeof(QOS_TRAFFIC_CLASS))
  542. return QOS_STATUS_TC_OBJECT_LENGTH_INVALID;
  543. Class = (((LPQOS_TRAFFIC_CLASS)QoSObject)->TrafficClass);
  544. if(Class > USER_PRIORITY_MAX_VALUE)
  545. {
  546. return QOS_STATUS_INVALID_TRAFFIC_CLASS;
  547. }
  548. break;
  549. case QOS_OBJECT_DS_CLASS:
  550. if (ParamsLength < sizeof(QOS_DS_CLASS))
  551. return QOS_STATUS_TC_OBJECT_LENGTH_INVALID;
  552. Class = (((LPQOS_DS_CLASS)QoSObject)->DSField);
  553. if(Class > PREC_MAX_VALUE)
  554. {
  555. return QOS_STATUS_INVALID_DS_CLASS;
  556. }
  557. break;
  558. case QOS_OBJECT_SHAPING_RATE:
  559. if (ParamsLength < sizeof(QOS_SHAPING_RATE))
  560. return QOS_STATUS_TC_OBJECT_LENGTH_INVALID;
  561. ShapingRate = (((LPQOS_SHAPING_RATE)QoSObject)->ShapingRate);
  562. if(ShapingRate == 0 || ShapingRate > TokenRate)
  563. {
  564. return QOS_STATUS_INVALID_SHAPE_RATE;
  565. }
  566. else
  567. {
  568. //
  569. // If this QoS object is present, we want to shape to this
  570. // rate.
  571. //
  572. Vc->ShapeTokenRate = ShapingRate;
  573. }
  574. break;
  575. case QOS_OBJECT_PRIORITY:
  576. if (ParamsLength < sizeof(QOS_PRIORITY))
  577. return QOS_STATUS_TC_OBJECT_LENGTH_INVALID;
  578. SendPriority = ((LPQOS_PRIORITY)QoSObject)->SendPriority;
  579. if((SendPriority < 0) || (SendPriority > 7)){
  580. // bad priority value - reject
  581. return(QOS_STATUS_INVALID_QOS_PRIORITY);
  582. }
  583. break;
  584. case QOS_OBJECT_SD_MODE:
  585. if (ParamsLength < sizeof(QOS_SD_MODE))
  586. return QOS_STATUS_TC_OBJECT_LENGTH_INVALID;
  587. SDMode = ((LPQOS_SD_MODE)QoSObject)->ShapeDiscardMode;
  588. //
  589. // Since SDMode is a ULONG, it can never be < TC_NONCONF_BORROW, which has a value of 0.
  590. // so, we just check to see if SDMode is > TC_NONCONF_BORROW_PLUS. This covers all cases.
  591. //
  592. if(SDMode > TC_NONCONF_BORROW_PLUS){
  593. // bad shape discard mode - reject
  594. return(QOS_STATUS_INVALID_SD_MODE);
  595. }
  596. if((SDMode > TC_NONCONF_BORROW) &&
  597. (TokenRate == UNSPECIFIED_RATE)){
  598. // must have TokenRate specified if any SDMode
  599. // other than TC_NONCONF_BORROW
  600. return(QOS_STATUS_INVALID_TOKEN_RATE);
  601. }
  602. break;
  603. // Pass any provider specific objects that we don't recognize
  604. default:
  605. return(QOS_STATUS_TC_OBJECT_LENGTH_INVALID);
  606. }
  607. if(
  608. ((LONG)QoSObject->ObjectLength <= 0) ||
  609. ((LONG)QoSObject->ObjectLength > ParamsLength)
  610. ) {
  611. return(QOS_STATUS_TC_OBJECT_LENGTH_INVALID);
  612. }
  613. ParamsLength -= QoSObject->ObjectLength;
  614. QoSObject = (LPQOS_OBJECT_HDR)((UINT_PTR)QoSObject +
  615. QoSObject->ObjectLength);
  616. }
  617. if (ParamsLength == sizeof(QOS_OBJECT_HDR)) {
  618. if (QoSObject->ObjectType != QOS_OBJECT_END_OF_LIST) {
  619. return(QOS_STATUS_TC_OBJECT_LENGTH_INVALID);
  620. }
  621. } else if (ParamsLength != 0) {
  622. return(QOS_STATUS_TC_OBJECT_LENGTH_INVALID);
  623. }
  624. //
  625. // If there is a specified PeakBandwidth, it must be geq to the
  626. // TokenRate - meaning - there must be a TokenRate specified also.
  627. // This is reasonable for LAN, although ATM does allow a
  628. // PeakBandwidth to be specified with no TokenRate.
  629. //
  630. // We also reject a TokenRate of zero.
  631. //
  632. if(PeakBandwidth != UNSPECIFIED_RATE){
  633. if(TokenRate == UNSPECIFIED_RATE){
  634. return(QOS_STATUS_INVALID_PEAK_RATE);
  635. }
  636. if(TokenRate > PeakBandwidth){
  637. return(QOS_STATUS_INVALID_PEAK_RATE);
  638. }
  639. }
  640. if(TokenRate == 0){
  641. return(QOS_STATUS_INVALID_TOKEN_RATE);
  642. }
  643. switch(ServiceType){
  644. case SERVICETYPE_BESTEFFORT:
  645. case SERVICETYPE_NETWORK_CONTROL:
  646. case SERVICETYPE_QUALITATIVE:
  647. break;
  648. case SERVICETYPE_CONTROLLEDLOAD:
  649. case SERVICETYPE_GUARANTEED:
  650. // Must specify a TokenRate for these services
  651. if(TokenRate == QOS_UNSPECIFIED) {
  652. return(QOS_STATUS_INVALID_TOKEN_RATE);
  653. }
  654. break;
  655. default:
  656. return(QOS_STATUS_INVALID_SERVICE_TYPE);
  657. }
  658. return(Status);
  659. }
  660. NDIS_STATUS
  661. AcquireFlowResources(
  662. PGPC_CLIENT_VC Vc,
  663. PCO_CALL_MANAGER_PARAMETERS NewCallParams,
  664. PCO_CALL_MANAGER_PARAMETERS OldCallParams,
  665. PULONG RemainingBandWidthChanged
  666. )
  667. /*++
  668. Routine Description:
  669. See if this adapter can support the requested flow. If it can,
  670. NDIS_STATUS_SUCCESS is returned, indicating that the resources
  671. have been committed.
  672. Arguments:
  673. Vc - pointer to vc's context block
  674. NewCallParams - struct describing the flow to add or to modify to.
  675. OldCallParams - in case of a modify, this describes the old params.
  676. Return Value:
  677. NDIS_STATUS_SUCCESS if everything worked ok
  678. --*/
  679. {
  680. PADAPTER Adapter;
  681. ULONG OldTokenRate;
  682. SERVICETYPE OldServiceType;
  683. ULONG NewTokenRate = NewCallParams->Transmit.TokenRate;
  684. SERVICETYPE NewServiceType = NewCallParams->Transmit.ServiceType;
  685. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  686. PULONG RemainingBandWidth;
  687. PULONG NonBestEffortLimit;
  688. PPS_SPIN_LOCK Lock;
  689. Adapter = Vc->Adapter;
  690. PsStructAssert(Adapter);
  691. *RemainingBandWidthChanged = FALSE;
  692. if(Adapter->MediaType == NdisMediumWan && (!IsBestEffortVc(Vc)))
  693. {
  694. RemainingBandWidth = &Vc->WanLink->RemainingBandWidth;
  695. NonBestEffortLimit = &Vc->WanLink->NonBestEffortLimit;
  696. Lock = &Vc->WanLink->Lock;
  697. return NDIS_STATUS_SUCCESS;
  698. }
  699. else
  700. {
  701. RemainingBandWidth = &Adapter->RemainingBandWidth;
  702. NonBestEffortLimit = &Adapter->NonBestEffortLimit;
  703. Lock = &Adapter->Lock;
  704. }
  705. if(OldCallParams)
  706. {
  707. OldTokenRate = OldCallParams->Transmit.TokenRate;
  708. OldServiceType = OldCallParams->Transmit.ServiceType;
  709. }
  710. //
  711. // sanity check passed; now see if we have the resouces locally
  712. //
  713. // for best-effort flows, the token rate, for the purpose of
  714. // admission control, is considered to be zero
  715. //
  716. if(NewServiceType == SERVICETYPE_BESTEFFORT || NewServiceType == SERVICETYPE_NETWORK_CONTROL ||
  717. NewServiceType == SERVICETYPE_QUALITATIVE)
  718. {
  719. NewTokenRate = 0;
  720. }
  721. //
  722. // Handle add differently from a modify
  723. //
  724. if(!OldCallParams){
  725. PS_LOCK(Lock);
  726. if((((LONG)(*RemainingBandWidth)) < 0) || (NewTokenRate > *RemainingBandWidth)){
  727. PS_UNLOCK(Lock);
  728. return(NDIS_STATUS_RESOURCES);
  729. }
  730. else{
  731. if(NewTokenRate) {
  732. *RemainingBandWidthChanged = TRUE;
  733. }
  734. *RemainingBandWidth -= NewTokenRate;
  735. //
  736. // Record the change we made, in case we have
  737. // to cancel the addition.
  738. //
  739. Vc->TokenRateChange = NewTokenRate;
  740. Vc->RemainingBandwidthIncreased = FALSE;
  741. PsAssert((*RemainingBandWidth <= *NonBestEffortLimit));
  742. PS_UNLOCK(Lock);
  743. }
  744. }
  745. else{
  746. //
  747. // it's a modify
  748. //
  749. // If the OldServiceType is best-effort,
  750. // then the OldTokenRate can be considered
  751. // to be zero, for the purpose of admission control.
  752. //
  753. if(OldServiceType == SERVICETYPE_BESTEFFORT ||
  754. OldServiceType == SERVICETYPE_NETWORK_CONTROL ||
  755. OldServiceType == SERVICETYPE_QUALITATIVE)
  756. {
  757. OldTokenRate = 0;
  758. }
  759. PS_LOCK(Lock);
  760. if(NewTokenRate != OldTokenRate){
  761. if((((LONG) *RemainingBandWidth) < 0 )||
  762. ((NewTokenRate > OldTokenRate) &&
  763. ((NewTokenRate - OldTokenRate) >
  764. (*RemainingBandWidth)))){
  765. //
  766. // asked for more and none was available
  767. //
  768. PS_UNLOCK( Lock );
  769. return(NDIS_STATUS_RESOURCES);
  770. }
  771. else{
  772. //
  773. // either asked for less or rate increment was available
  774. //
  775. *RemainingBandWidth -= NewTokenRate;
  776. *RemainingBandWidth += OldTokenRate;
  777. if((NewTokenRate != 0) || (OldTokenRate != 0)) {
  778. *RemainingBandWidthChanged = TRUE;
  779. }
  780. //
  781. // Now we've acquired the resources. If
  782. // the VC activation fails for any reason,
  783. // we'll need to return resources. We should
  784. // return the difference between the old token
  785. // rate and the new token rate, not the new token
  786. // rate.
  787. //
  788. if(NewTokenRate > OldTokenRate){
  789. // Can't use signed ints, cause we'll lose range
  790. Vc->TokenRateChange = NewTokenRate - OldTokenRate;
  791. Vc->RemainingBandwidthIncreased = FALSE;
  792. }
  793. else{
  794. Vc->TokenRateChange = OldTokenRate - NewTokenRate;
  795. Vc->RemainingBandwidthIncreased = TRUE;
  796. }
  797. PS_UNLOCK( Lock );
  798. }
  799. }
  800. else{
  801. PS_UNLOCK(Lock);
  802. }
  803. }
  804. return Status;
  805. } // AcquireFlowResources
  806. VOID
  807. CancelAcquiredFlowResources(
  808. PGPC_CLIENT_VC Vc
  809. )
  810. /*++
  811. Routine Description:
  812. Called when a modify or add flwo failed, after we did admission control.
  813. Arguments:
  814. Vc - pointer to client vc's context block
  815. Return Value:
  816. None
  817. --*/
  818. {
  819. PADAPTER Adapter;
  820. PPS_SPIN_LOCK Lock;
  821. PULONG RemainingBandWidth;
  822. Adapter = Vc->Adapter;
  823. PsStructAssert(Adapter);
  824. if(Adapter->MediaType == NdisMediumWan && (!IsBestEffortVc(Vc)))
  825. {
  826. Lock = &Vc->WanLink->Lock;
  827. RemainingBandWidth = &Vc->WanLink->RemainingBandWidth;
  828. return;
  829. }
  830. else
  831. {
  832. Lock = &Adapter->Lock;
  833. RemainingBandWidth = &Adapter->RemainingBandWidth;
  834. }
  835. if(!Vc->TokenRateChange){
  836. return;
  837. }
  838. PS_LOCK( Lock );
  839. if(Vc->RemainingBandwidthIncreased){
  840. *RemainingBandWidth -= Vc->TokenRateChange;
  841. }
  842. else{
  843. *RemainingBandWidth += Vc->TokenRateChange;
  844. }
  845. //
  846. // Now that we have already returned the correct TokenRate, we need to set it to 0
  847. // so that this is not used in subsequent VC operations.
  848. //
  849. Vc->TokenRateChange = 0;
  850. // PsAssert(Adapter->RemainingBandWidth <= Adapter->NonBestEffortLimit);
  851. PS_UNLOCK( Lock );
  852. } // CancelAcquiredFlowResources
  853. VOID
  854. ReturnFlowResources(
  855. PGPC_CLIENT_VC Vc,
  856. PULONG RemainingBandWidthChanged
  857. )
  858. /*++
  859. Routine Description:
  860. Return all the resources acquired for this flow
  861. Arguments:
  862. Vc - pointer to client vc's context block
  863. Return Value:
  864. None
  865. --*/
  866. {
  867. PADAPTER Adapter;
  868. PCO_CALL_MANAGER_PARAMETERS CmParams = Vc->CallParameters->CallMgrParameters;
  869. ULONG TokenRate = CmParams->Transmit.TokenRate;
  870. SERVICETYPE ServiceType = CmParams->Transmit.ServiceType;
  871. PPS_SPIN_LOCK Lock;
  872. PULONG RemainingBandWidth;
  873. Adapter = Vc->Adapter;
  874. PsStructAssert(Adapter);
  875. *RemainingBandWidthChanged = FALSE;
  876. if(Adapter->MediaType == NdisMediumWan && (!IsBestEffortVc(Vc)))
  877. {
  878. RemainingBandWidth = &Vc->WanLink->RemainingBandWidth;
  879. Lock = &Vc->WanLink->Lock;
  880. return;
  881. }
  882. else
  883. {
  884. RemainingBandWidth = &Adapter->RemainingBandWidth;
  885. Lock = &Adapter->Lock;
  886. }
  887. if (ServiceType == SERVICETYPE_BESTEFFORT ||
  888. ServiceType == SERVICETYPE_NETWORK_CONTROL ||
  889. ServiceType == SERVICETYPE_QUALITATIVE)
  890. {
  891. return;
  892. }
  893. *RemainingBandWidthChanged = TRUE;
  894. PsAssert((LONG)TokenRate > 0);
  895. PS_LOCK( Lock );
  896. *RemainingBandWidth += TokenRate;
  897. // PsAssert(Adapter->RemainingBandWidth <= Adapter->NonBestEffortLimit);
  898. PS_UNLOCK( Lock );
  899. } // ReturnFlowResources
  900. NDIS_STATUS
  901. CreateBestEffortVc(
  902. PADAPTER Adapter,
  903. PGPC_CLIENT_VC Vc,
  904. PPS_WAN_LINK WanLink
  905. )
  906. {
  907. PCO_CALL_PARAMETERS CallParams;
  908. PCO_CALL_MANAGER_PARAMETERS CallMgrParameters;
  909. PCO_MEDIA_PARAMETERS MediaParameters;
  910. ULONG CallParamsLength;
  911. NDIS_STATUS Status;
  912. int i;
  913. InitGpcClientVc(Vc, GPC_CLIENT_BEST_EFFORT_VC, Adapter);
  914. SetLLTag(Vc, GpcClientVc);
  915. //
  916. // Invalidate all the port numbers
  917. for( i = 0; i < PORT_LIST_LEN; i++)
  918. {
  919. Vc->SrcPort[i] = 0;
  920. Vc->DstPort[i] = 0;
  921. }
  922. // Next Insertion will be at index 0
  923. Vc->NextSlot = 0;
  924. //
  925. // Allocate the resources for the call manager parameters.
  926. //
  927. CallParamsLength = sizeof(CO_CALL_PARAMETERS) +
  928. sizeof(CO_CALL_MANAGER_PARAMETERS) +
  929. sizeof(QOS_SD_MODE) +
  930. sizeof(QOS_OBJECT_HDR) +
  931. FIELD_OFFSET(CO_MEDIA_PARAMETERS, MediaSpecific) +
  932. FIELD_OFFSET(CO_SPECIFIC_PARAMETERS, Parameters);
  933. if(Adapter->MediaType == NdisMediumWan)
  934. {
  935. CallParamsLength += sizeof(QOS_WAN_MEDIA);
  936. Vc->PsPipeContext = WanLink->PsPipeContext;
  937. Vc->PsComponent = WanLink->PsComponent;
  938. Vc->AdapterStats = &WanLink->Stats;
  939. Vc->WanLink = WanLink;
  940. Vc->Flags |= GPC_WANLINK_VC;
  941. if(Adapter->BestEffortLimit != UNSPECIFIED_RATE)
  942. {
  943. //
  944. // If LBE is specified over WAN, use UBE
  945. //
  946. PsAdapterWriteEventLog(
  947. EVENT_PS_WAN_LIMITED_BESTEFFORT,
  948. 0,
  949. &Adapter->MpDeviceName,
  950. 0,
  951. NULL);
  952. Adapter->BestEffortLimit = UNSPECIFIED_RATE;
  953. }
  954. }
  955. else
  956. {
  957. Vc->PsPipeContext = Adapter->PsPipeContext;
  958. Vc->PsComponent = Adapter->PsComponent;
  959. Vc->AdapterStats = &Adapter->Stats;
  960. }
  961. PsAllocatePool(CallParams, CallParamsLength, CmParamsTag);
  962. if(CallParams == NULL)
  963. {
  964. return NDIS_STATUS_RESOURCES;
  965. }
  966. //
  967. // build a call params struct describing the flow
  968. //
  969. NdisZeroMemory(CallParams, CallParamsLength);
  970. //
  971. // Build the Call Manager Parameters.
  972. //
  973. CallMgrParameters = (PCO_CALL_MANAGER_PARAMETERS)(CallParams + 1);
  974. if(Adapter->BestEffortLimit == UNSPECIFIED_RATE)
  975. {
  976. FillInCmParams(CallMgrParameters,
  977. SERVICETYPE_BESTEFFORT,
  978. (ULONG)UNSPECIFIED_RATE,
  979. (ULONG)UNSPECIFIED_RATE,
  980. Adapter->TotalSize,
  981. QOS_UNSPECIFIED,
  982. QOS_UNSPECIFIED);
  983. }
  984. else
  985. {
  986. //
  987. // Limited Best Effort
  988. //
  989. PsAssert(Adapter->MediaType != NdisMediumWan);
  990. if(Adapter->BestEffortLimit >= Adapter->LinkSpeed) {
  991. // If the specified limit is greater than the link speed,
  992. // then we should operate in unlimited best-effort mode.
  993. PsAdapterWriteEventLog(
  994. EVENT_PS_BAD_BESTEFFORT_LIMIT,
  995. 0,
  996. &Adapter->MpDeviceName,
  997. 0,
  998. NULL);
  999. PsDbgOut(DBG_INFO,
  1000. DBG_PROTOCOL,
  1001. ("[CreateBestEffortVc]: b/e limit %d exceeds link speed %d\n",
  1002. Adapter->BestEffortLimit,
  1003. Adapter->LinkSpeed));
  1004. Adapter->BestEffortLimit = UNSPECIFIED_RATE;
  1005. FillInCmParams(CallMgrParameters,
  1006. SERVICETYPE_BESTEFFORT,
  1007. (ULONG)UNSPECIFIED_RATE,
  1008. (ULONG)UNSPECIFIED_RATE,
  1009. Adapter->TotalSize,
  1010. QOS_UNSPECIFIED,
  1011. QOS_UNSPECIFIED);
  1012. }
  1013. else
  1014. {
  1015. FillInCmParams(CallMgrParameters,
  1016. SERVICETYPE_BESTEFFORT,
  1017. Adapter->BestEffortLimit,
  1018. (ULONG)UNSPECIFIED_RATE,
  1019. Adapter->TotalSize,
  1020. TC_NONCONF_SHAPE,
  1021. QOS_UNSPECIFIED);
  1022. }
  1023. }
  1024. //
  1025. // Build the MediaParameters.
  1026. //
  1027. CallParams->MediaParameters =
  1028. (PCO_MEDIA_PARAMETERS)(CallMgrParameters + 1);
  1029. MediaParameters = (PCO_MEDIA_PARAMETERS)((PUCHAR)
  1030. CallMgrParameters +
  1031. sizeof(CO_CALL_MANAGER_PARAMETERS) +
  1032. sizeof(QOS_SD_MODE) +
  1033. sizeof(QOS_OBJECT_HDR));
  1034. MediaParameters->Flags = 0;
  1035. MediaParameters->ReceivePriority = 0;
  1036. MediaParameters->ReceiveSizeHint = 0;
  1037. MediaParameters->MediaSpecific.ParamType = PARAM_TYPE_GQOS_INFO;
  1038. MediaParameters->MediaSpecific.Length = 0;
  1039. CallParams->Flags = 0;
  1040. CallParams->CallMgrParameters = CallMgrParameters;
  1041. CallParams->MediaParameters = (PCO_MEDIA_PARAMETERS)MediaParameters;
  1042. if(Adapter->MediaType == NdisMediumWan) {
  1043. LPQOS_WAN_MEDIA WanMedia;
  1044. MediaParameters->MediaSpecific.Length += sizeof(QOS_WAN_MEDIA);
  1045. WanMedia = (LPQOS_WAN_MEDIA) MediaParameters->MediaSpecific.Parameters;
  1046. NdisZeroMemory(WanMedia, sizeof(QOS_WAN_MEDIA));
  1047. WanMedia->ObjectHdr.ObjectType = QOS_OBJECT_WAN_MEDIA;
  1048. WanMedia->ObjectHdr.ObjectLength = sizeof(QOS_WAN_MEDIA);
  1049. NdisMoveMemory(&WanMedia->LinkId,
  1050. &WanLink->OriginalRemoteMacAddress,
  1051. 6);
  1052. }
  1053. Vc->CallParameters = CallParams;
  1054. Status = CmMakeCall(Vc);
  1055. PsAssert(Status != NDIS_STATUS_PENDING);
  1056. if(Status == NDIS_STATUS_SUCCESS)
  1057. {
  1058. REFADD(&Adapter->RefCount, 'ADVC');
  1059. if(Adapter->MediaType == NdisMediumWan)
  1060. {
  1061. REFADD(&WanLink->RefCount, 'WANV');
  1062. }
  1063. //
  1064. // Also save the non conforming value - so that the sequencer can stamp it
  1065. // for non conforming packets. This will not change between reboots & hence
  1066. // need not be done in the ModifyCfInfo
  1067. //
  1068. Vc->UserPriorityNonConforming = Adapter->UserServiceTypeNonConforming;
  1069. switch(Vc->CallParameters->CallMgrParameters->Transmit.ServiceType)
  1070. {
  1071. case SERVICETYPE_CONTROLLEDLOAD:
  1072. Vc->UserPriorityConforming = Adapter->UserServiceTypeControlledLoad;
  1073. Vc->IPPrecedenceNonConforming = Adapter->IPServiceTypeControlledLoadNC;
  1074. break;
  1075. case SERVICETYPE_GUARANTEED:
  1076. Vc->UserPriorityConforming = Adapter->UserServiceTypeGuaranteed;
  1077. Vc->IPPrecedenceNonConforming = Adapter->IPServiceTypeGuaranteedNC;
  1078. break;
  1079. case SERVICETYPE_BESTEFFORT:
  1080. Vc->UserPriorityConforming = Adapter->UserServiceTypeBestEffort;
  1081. Vc->IPPrecedenceNonConforming = Adapter->IPServiceTypeBestEffortNC;
  1082. break;
  1083. case SERVICETYPE_QUALITATIVE:
  1084. Vc->UserPriorityConforming = Adapter->UserServiceTypeQualitative;
  1085. Vc->IPPrecedenceNonConforming = Adapter->IPServiceTypeQualitativeNC;
  1086. break;
  1087. case SERVICETYPE_NETWORK_CONTROL:
  1088. Vc->UserPriorityConforming = Adapter->UserServiceTypeNetworkControl;
  1089. Vc->IPPrecedenceNonConforming = Adapter->IPServiceTypeNetworkControlNC;
  1090. break;
  1091. }
  1092. //
  1093. // Transistion to the Call complete state
  1094. //
  1095. CallSucceededStateTransition(Vc);
  1096. }
  1097. return Status;
  1098. }
  1099. /* end cmvc.c */