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.

634 lines
16 KiB

  1. /*++
  2. Copyright (c) 1996-1999 Microsoft Corporation
  3. Module Name:
  4. mpvc.c
  5. Abstract:
  6. miniport handlers for VC mgmt
  7. Author:
  8. Charlie Wickham (charlwi) 13-Sep-1996
  9. Rajesh Sundaram (rajeshsu) 01-Aug-1998.
  10. Environment:
  11. Kernel Mode
  12. Revision History:
  13. --*/
  14. #include "psched.h"
  15. #pragma hdrstop
  16. /* External */
  17. /* Static */
  18. /* Forward */
  19. NDIS_STATUS
  20. GetSchedulerFlowContext(
  21. PGPC_CLIENT_VC AdapterVc
  22. );
  23. NDIS_STATUS
  24. MpDeactivateVc(
  25. IN NDIS_HANDLE MiniportVcContext
  26. );
  27. HANDLE
  28. GetNdisFlowHandle (
  29. IN HANDLE PsFlowContext
  30. );
  31. /* End Forward */
  32. NDIS_STATUS
  33. AddFlowToScheduler(
  34. IN ULONG Operation,
  35. IN PGPC_CLIENT_VC Vc,
  36. IN OUT PCO_CALL_PARAMETERS NewCallParameters,
  37. IN OUT PCO_CALL_PARAMETERS OldCallParameters
  38. )
  39. /*++
  40. Routine Description:
  41. Add the Vc to the scheduler.
  42. Arguments:
  43. See the DDK...
  44. Return Values:
  45. None
  46. --*/
  47. {
  48. PADAPTER Adapter = Vc->Adapter;
  49. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  50. PCO_CALL_MANAGER_PARAMETERS NewCmParams;
  51. PCO_CALL_MANAGER_PARAMETERS OldCmParams;
  52. SERVICETYPE ServiceType;
  53. ULONG ParamsLength;
  54. LPQOS_OBJECT_HDR QoSObject;
  55. ULONG OriginalTokenRate;
  56. CheckLLTag(Vc, GpcClientVc);
  57. PsStructAssert(Adapter);
  58. PsDbgOut(DBG_TRACE,
  59. DBG_VC,
  60. ("(%08X) AddFlowToScheduler\n",
  61. Vc));
  62. NewCmParams = NewCallParameters->CallMgrParameters;
  63. ServiceType = NewCmParams->Transmit.ServiceType;
  64. //
  65. // We might need to change the rate at which the scheduling components shape the packet.
  66. //
  67. OriginalTokenRate = NewCmParams->Transmit.TokenRate;
  68. NewCmParams->Transmit.TokenRate = Vc->ShapeTokenRate;
  69. //
  70. // Is this a new VC? or a modification of an existing VC?
  71. //
  72. PS_LOCK(&Adapter->Lock);
  73. if(Operation == NEW_VC){
  74. PsAssert(!OldCallParameters);
  75. //
  76. // New Vc.
  77. //
  78. // Check the type of service we're activating. If best
  79. // effort and we're limiting total best effort bandwidth,
  80. // and it's not our internal best effort vc, then we don't
  81. // want to add the flow in the scheduler.
  82. //
  83. if((ServiceType == SERVICETYPE_BESTEFFORT) &&
  84. (Adapter->BestEffortLimit != UNSPECIFIED_RATE) &&
  85. !IsBestEffortVc(Vc)){
  86. PS_UNLOCK(&Adapter->Lock);
  87. //
  88. // Just merge the VC into the internal, existing best
  89. // effort VC. The internal best-effort VC is created
  90. // internally without calling AddFlowToScheduler.
  91. //
  92. // Give this VC the same flow context as our internal.
  93. // The scheduler then thinks it is all the same VC
  94. //
  95. if(Adapter->MediaType == NdisMediumWan) {
  96. Vc->PsFlowContext = Vc->WanLink->BestEffortVc.PsFlowContext;
  97. }
  98. else {
  99. Vc->PsFlowContext = Adapter->BestEffortVc.PsFlowContext;
  100. }
  101. Status = NDIS_STATUS_SUCCESS;
  102. }
  103. else{
  104. //
  105. // Need to actually create a new flow in the scheduler.
  106. // first allocate the flow context buffer
  107. //
  108. PS_UNLOCK(&Adapter->Lock);
  109. Status = GetSchedulerFlowContext(Vc);
  110. if(Status != NDIS_STATUS_SUCCESS){
  111. goto Exit;
  112. }
  113. Status = (*Vc->PsComponent->CreateFlow)(
  114. Vc->PsPipeContext,
  115. Vc,
  116. NewCallParameters,
  117. Vc->PsFlowContext);
  118. }
  119. }
  120. else{
  121. //
  122. // Must be a modify. Check old params.
  123. OldCmParams = OldCallParameters->CallMgrParameters;
  124. //
  125. // If BestEffortLimit != UNSPECIFIED_RATE, then there
  126. // are two special cases we have to handle:
  127. //
  128. // 1. A non-private flow, created for SERVICETYPE_BESTEFFORT
  129. // is being modified to a ServiceType other than best-effort.
  130. //
  131. // 2. A non-private flow, created for a ServiceType other
  132. // than best-effort, is now being modified to best-effort.
  133. //
  134. // In the first case, we have to call the scheduler to
  135. // create a flow, since previously the client's flow was
  136. // just merged with a single best-effort flow.
  137. //
  138. // In the second case, we have to close the flow that existed
  139. // and remap the client's flow to the single best-efort flow,
  140. // thereby merging the client's flow with the existing b/e
  141. // flow.
  142. //
  143. if((Adapter->BestEffortLimit != UNSPECIFIED_RATE) &&
  144. (OldCmParams->Transmit.ServiceType == SERVICETYPE_BESTEFFORT) &&
  145. (NewCmParams->Transmit.ServiceType != SERVICETYPE_BESTEFFORT)){
  146. //
  147. // Unmerge
  148. //
  149. PS_UNLOCK(&Adapter->Lock);
  150. Status = GetSchedulerFlowContext(Vc);
  151. if(Status != NDIS_STATUS_SUCCESS){
  152. goto Exit;
  153. }
  154. Status = (*Vc->PsComponent->CreateFlow)(
  155. Vc->PsPipeContext,
  156. Vc,
  157. NewCallParameters,
  158. Vc->PsFlowContext);
  159. }
  160. else{
  161. if((Adapter->BestEffortLimit != UNSPECIFIED_RATE) &&
  162. (OldCmParams->Transmit.ServiceType != SERVICETYPE_BESTEFFORT) &&
  163. (NewCmParams->Transmit.ServiceType == SERVICETYPE_BESTEFFORT)){
  164. //
  165. // Merge
  166. //
  167. PS_UNLOCK(&Adapter->Lock);
  168. (*Vc->PsComponent->DeleteFlow)(
  169. Vc->PsPipeContext,
  170. Vc->PsFlowContext);
  171. Vc->PsFlowContext = Adapter->BestEffortVc.PsFlowContext;
  172. Status = NDIS_STATUS_SUCCESS;
  173. }
  174. else{
  175. PS_UNLOCK(&Adapter->Lock);
  176. Status = (*Vc->PsComponent->ModifyFlow)(
  177. Vc->PsPipeContext,
  178. Vc->PsFlowContext,
  179. NewCallParameters);
  180. }
  181. }
  182. } // Modify
  183. Exit:
  184. //
  185. // Revert the call parameters.
  186. //
  187. NewCmParams->Transmit.TokenRate = OriginalTokenRate;
  188. return(Status);
  189. } // AddFlowToScheduler
  190. NDIS_STATUS
  191. GetSchedulerFlowContext(
  192. PGPC_CLIENT_VC AdapterVc
  193. )
  194. /*++
  195. Routine Description:
  196. Allocate the pipe context area for the scheduler.
  197. Arguments:
  198. AdapterVc- pointer to adapter VC context struct
  199. Return Value:
  200. NDIS_STATUS_SUCCESS, otherwise appropriate error value
  201. --*/
  202. {
  203. PADAPTER Adapter = AdapterVc->Adapter;
  204. NDIS_STATUS Status;
  205. PPSI_INFO *SchedulerConfig;
  206. PPSI_INFO PsComponent = AdapterVc->PsComponent;
  207. ULONG ContextLength = 0;
  208. ULONG FlowContextLength = 0;
  209. ULONG Index = 0;
  210. PPS_PIPE_CONTEXT PipeContext = AdapterVc->PsPipeContext;
  211. PPS_FLOW_CONTEXT FlowContext;
  212. PPS_FLOW_CONTEXT PrevContext;
  213. //
  214. // The length of the flow context buffer for this pipe was calculated
  215. // when the pipe was initialized.
  216. //
  217. PsAllocatePool(AdapterVc->PsFlowContext,
  218. Adapter->FlowContextLength,
  219. FlowContextTag );
  220. if ( AdapterVc->PsFlowContext == NULL ) {
  221. return NDIS_STATUS_RESOURCES;
  222. }
  223. // Set up the context buffer
  224. FlowContext = (PPS_FLOW_CONTEXT)AdapterVc->PsFlowContext;
  225. PrevContext = NULL;
  226. while (PsComponent != NULL) {
  227. FlowContext->NextComponentContext = (PPS_FLOW_CONTEXT)
  228. ((UINT_PTR)FlowContext + PsComponent->FlowContextLength);
  229. FlowContext->PrevComponentContext = PrevContext;
  230. PsComponent = PipeContext->NextComponent;
  231. PipeContext = PipeContext->NextComponentContext;
  232. PrevContext = FlowContext;
  233. FlowContext = FlowContext->NextComponentContext;
  234. }
  235. return NDIS_STATUS_SUCCESS;
  236. } // GetSchedulerFlowContext
  237. NDIS_STATUS
  238. EmptyPacketsFromScheduler(
  239. PGPC_CLIENT_VC Vc
  240. )
  241. /*++
  242. Routine Description:
  243. Cleans up (DROPS) the pending packets on this Vc in each of the components
  244. --*/
  245. {
  246. PADAPTER Adapter = Vc->Adapter;
  247. NDIS_STATUS Status;
  248. CheckLLTag(Vc, GpcClientVc);
  249. PsStructAssert(Adapter);
  250. PsDbgOut(DBG_TRACE,
  251. DBG_VC,
  252. ("(%08X) EmptyPacketsFromScheduler\n", Vc));
  253. if(Adapter->MediaType == NdisMediumWan) {
  254. if(Vc->PsFlowContext != Vc->WanLink->BestEffortVc.PsFlowContext){
  255. //
  256. // Different context - definitely should be removed.
  257. //
  258. (*Vc->PsComponent->EmptyFlow)(Vc->PsPipeContext,
  259. Vc->PsFlowContext);
  260. }
  261. else {
  262. //
  263. // Same context. Remove only if it is actually the best-effort
  264. // VC.
  265. //
  266. if(Vc == &Vc->WanLink->BestEffortVc){
  267. (*Vc->PsComponent->EmptyFlow)(Vc->PsPipeContext,
  268. Vc->PsFlowContext);
  269. }
  270. }
  271. }
  272. else {
  273. if(Vc->PsFlowContext != Adapter->BestEffortVc.PsFlowContext){
  274. //
  275. // Different context - definitely should be removed.
  276. //
  277. (*Vc->PsComponent->EmptyFlow)(Vc->PsPipeContext,
  278. Vc->PsFlowContext);
  279. }
  280. else {
  281. //
  282. // Same context. Remove only if it is actually the best-effort
  283. // VC.
  284. //
  285. if(Vc == &Adapter->BestEffortVc){
  286. (*Vc->PsComponent->EmptyFlow)(Vc->PsPipeContext,
  287. Vc->PsFlowContext);
  288. }
  289. }
  290. }
  291. return NDIS_STATUS_SUCCESS;
  292. }
  293. NDIS_STATUS
  294. RemoveFlowFromScheduler(
  295. PGPC_CLIENT_VC Vc
  296. )
  297. /*++
  298. Routine Description:
  299. Notify the PSA that the flow is going away
  300. Arguments:
  301. See the DDK...
  302. Return Values:
  303. None
  304. --*/
  305. {
  306. PADAPTER Adapter = Vc->Adapter;
  307. NDIS_STATUS Status;
  308. CheckLLTag(Vc, GpcClientVc);
  309. PsStructAssert(Adapter);
  310. PsDbgOut(DBG_TRACE,
  311. DBG_VC,
  312. ("(%08X) RemoveFlowFromScheduler\n", Vc));
  313. //
  314. // if this is a user vc which is merged into the scheduler's
  315. // internal best effort flow, then delete the vc without affecting
  316. // the scheduler. if it is not, then remove it from the scheduler
  317. // and delete the vc.
  318. //
  319. if(Adapter->MediaType == NdisMediumWan) {
  320. if(Vc->PsFlowContext != Vc->WanLink->BestEffortVc.PsFlowContext){
  321. //
  322. // Different context - definitely should be removed.
  323. //
  324. (*Vc->PsComponent->DeleteFlow)(Vc->PsPipeContext,
  325. Vc->PsFlowContext);
  326. }
  327. else {
  328. //
  329. // Same context. Remove only if it is actually the best-effort
  330. // VC.
  331. //
  332. if(Vc == &Vc->WanLink->BestEffortVc){
  333. (*Vc->PsComponent->DeleteFlow)(Vc->PsPipeContext,
  334. Vc->PsFlowContext);
  335. }
  336. }
  337. }
  338. else {
  339. if(Vc->PsFlowContext != Adapter->BestEffortVc.PsFlowContext){
  340. //
  341. // Different context - definitely should be removed.
  342. //
  343. (*Vc->PsComponent->DeleteFlow)(Vc->PsPipeContext,
  344. Vc->PsFlowContext);
  345. }
  346. else {
  347. //
  348. // Same context. Remove only if it is actually the best-effort
  349. // VC.
  350. //
  351. if(Vc == &Adapter->BestEffortVc){
  352. (*Vc->PsComponent->DeleteFlow)(Vc->PsPipeContext,
  353. Vc->PsFlowContext);
  354. }
  355. }
  356. }
  357. return NDIS_STATUS_SUCCESS;
  358. } // RemoveFlowFromScheduler
  359. NTSTATUS
  360. ModifyBestEffortBandwidth(
  361. PADAPTER Adapter,
  362. ULONG BestEffortRate)
  363. {
  364. PCO_CALL_PARAMETERS CallParams;
  365. PCO_CALL_MANAGER_PARAMETERS CallMgrParameters;
  366. ULONG CallParamsLength;
  367. PGPC_CLIENT_VC Vc;
  368. NDIS_STATUS Status;
  369. PsStructAssert(Adapter);
  370. Vc = &Adapter->BestEffortVc;
  371. CheckLLTag(Vc, GpcClientVc);
  372. //
  373. // This handles a TC API request to modify the default
  374. // best-effort bandwidth. Note that the b/e bandwidth
  375. // can only be modified if the PS is in limited b/e mode.
  376. //
  377. // Also - note that the b/e bandwidth can only be modified
  378. // while the adapter is in the Running state. We do not
  379. // have to worry about locking the VC since the b/e VC
  380. // will not be manipulated while it is in the running state
  381. // except by this thread.
  382. //
  383. PS_LOCK(&Adapter->Lock);
  384. if((Adapter->BestEffortLimit == UNSPECIFIED_RATE))
  385. {
  386. PS_UNLOCK(&Adapter->Lock);
  387. return(STATUS_WMI_NOT_SUPPORTED);
  388. }
  389. if((BestEffortRate > Adapter->LinkSpeed) ||
  390. (BestEffortRate == 0)){
  391. PS_UNLOCK(&Adapter->Lock);
  392. return(STATUS_INVALID_PARAMETER);
  393. }
  394. else{
  395. if(Adapter->PsMpState != AdapterStateRunning){
  396. PS_UNLOCK(&Adapter->Lock);
  397. return(STATUS_WMI_NOT_SUPPORTED);
  398. }
  399. CallParamsLength = sizeof(CO_CALL_PARAMETERS) +
  400. sizeof(CO_CALL_MANAGER_PARAMETERS) +
  401. sizeof(QOS_SD_MODE) +
  402. sizeof(QOS_OBJECT_HDR);
  403. PsAllocatePool(CallParams, CallParamsLength, CmParamsTag);
  404. if(CallParams == NULL){
  405. PS_UNLOCK(&Adapter->Lock);
  406. PsDbgOut(DBG_FAILURE, DBG_VC,
  407. ("ModifyBestEffortBandwidth: can't allocate call parms\n"));
  408. return(STATUS_INSUFFICIENT_RESOURCES);
  409. }
  410. //
  411. // build a call params struct describing the flow
  412. //
  413. CallMgrParameters = (PCO_CALL_MANAGER_PARAMETERS)(CallParams + 1);
  414. NdisFillMemory(CallParams,
  415. CallParamsLength,
  416. (UCHAR)QOS_UNSPECIFIED);
  417. CallParams->Flags = 0;
  418. CallParams->CallMgrParameters = CallMgrParameters;
  419. CallParams->MediaParameters = NULL;
  420. FillInCmParams(CallMgrParameters,
  421. SERVICETYPE_BESTEFFORT,
  422. BestEffortRate,
  423. (ULONG)UNSPECIFIED_RATE,
  424. Adapter->TotalSize,
  425. TC_NONCONF_SHAPE,
  426. QOS_UNSPECIFIED);
  427. Status = (*Vc->PsComponent->ModifyFlow)(
  428. Vc->PsPipeContext,
  429. Vc->PsFlowContext,
  430. CallParams);
  431. if(Status == NDIS_STATUS_SUCCESS){
  432. Adapter->BestEffortLimit = BestEffortRate;
  433. }
  434. PS_UNLOCK(&Adapter->Lock);
  435. PsFreePool(CallParams);
  436. return(Status);
  437. }
  438. }
  439. /* end mpvc.c */