PHSModule.c 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703
  1. #include "headers.h"
  2. static UINT CreateSFToClassifierRuleMapping(B_UINT16 uiVcid,
  3. B_UINT16 uiClsId,
  4. struct bcm_phs_table *psServiceFlowTable,
  5. struct bcm_phs_rule *psPhsRule,
  6. B_UINT8 u8AssociatedPHSI);
  7. static UINT CreateClassiferToPHSRuleMapping(B_UINT16 uiVcid,
  8. B_UINT16 uiClsId,
  9. struct bcm_phs_entry *pstServiceFlowEntry,
  10. struct bcm_phs_rule *psPhsRule,
  11. B_UINT8 u8AssociatedPHSI);
  12. static UINT CreateClassifierPHSRule(B_UINT16 uiClsId,
  13. struct bcm_phs_classifier_table *psaClassifiertable,
  14. struct bcm_phs_rule *psPhsRule,
  15. enum bcm_phs_classifier_context eClsContext,
  16. B_UINT8 u8AssociatedPHSI);
  17. static UINT UpdateClassifierPHSRule(B_UINT16 uiClsId,
  18. struct bcm_phs_classifier_entry *pstClassifierEntry,
  19. struct bcm_phs_classifier_table *psaClassifiertable,
  20. struct bcm_phs_rule *psPhsRule,
  21. B_UINT8 u8AssociatedPHSI);
  22. static bool ValidatePHSRuleComplete(const struct bcm_phs_rule *psPhsRule);
  23. static bool DerefPhsRule(B_UINT16 uiClsId,
  24. struct bcm_phs_classifier_table *psaClassifiertable,
  25. struct bcm_phs_rule *pstPhsRule);
  26. static UINT GetClassifierEntry(struct bcm_phs_classifier_table *pstClassifierTable,
  27. B_UINT32 uiClsid,
  28. enum bcm_phs_classifier_context eClsContext,
  29. struct bcm_phs_classifier_entry **ppstClassifierEntry);
  30. static UINT GetPhsRuleEntry(struct bcm_phs_classifier_table *pstClassifierTable,
  31. B_UINT32 uiPHSI,
  32. enum bcm_phs_classifier_context eClsContext,
  33. struct bcm_phs_rule **ppstPhsRule);
  34. static void free_phs_serviceflow_rules(struct bcm_phs_table *psServiceFlowRulesTable);
  35. static int phs_compress(struct bcm_phs_rule *phs_members,
  36. unsigned char *in_buf,
  37. unsigned char *out_buf,
  38. unsigned int *header_size,
  39. UINT *new_header_size);
  40. static int verify_suppress_phsf(unsigned char *in_buffer,
  41. unsigned char *out_buffer,
  42. unsigned char *phsf,
  43. unsigned char *phsm,
  44. unsigned int phss,
  45. unsigned int phsv,
  46. UINT *new_header_size);
  47. static int phs_decompress(unsigned char *in_buf,
  48. unsigned char *out_buf,
  49. struct bcm_phs_rule *phs_rules,
  50. UINT *header_size);
  51. static ULONG PhsCompress(void *pvContext,
  52. B_UINT16 uiVcid,
  53. B_UINT16 uiClsId,
  54. void *pvInputBuffer,
  55. void *pvOutputBuffer,
  56. UINT *pOldHeaderSize,
  57. UINT *pNewHeaderSize);
  58. static ULONG PhsDeCompress(void *pvContext,
  59. B_UINT16 uiVcid,
  60. void *pvInputBuffer,
  61. void *pvOutputBuffer,
  62. UINT *pInHeaderSize,
  63. UINT *pOutHeaderSize);
  64. #define IN
  65. #define OUT
  66. /*
  67. * Function: PHSTransmit
  68. * Description: This routine handle PHS(Payload Header Suppression for Tx path.
  69. * It extracts a fragment of the NDIS_PACKET containing the header
  70. * to be suppressed. It then suppresses the header by invoking PHS exported compress routine.
  71. * The header data after suppression is copied back to the NDIS_PACKET.
  72. *
  73. * Input parameters: IN struct bcm_mini_adapter *Adapter - Miniport Adapter Context
  74. * IN Packet - NDIS packet containing data to be transmitted
  75. * IN USHORT Vcid - vcid pertaining to connection on which the packet is being sent.Used to
  76. * identify PHS rule to be applied.
  77. * B_UINT16 uiClassifierRuleID - Classifier Rule ID
  78. * BOOLEAN bHeaderSuppressionEnabled - indicates if header suprression is enabled for SF.
  79. *
  80. * Return: STATUS_SUCCESS - If the send was successful.
  81. * Other - If an error occurred.
  82. */
  83. int PHSTransmit(struct bcm_mini_adapter *Adapter,
  84. struct sk_buff **pPacket,
  85. USHORT Vcid,
  86. B_UINT16 uiClassifierRuleID,
  87. bool bHeaderSuppressionEnabled,
  88. UINT *PacketLen,
  89. UCHAR bEthCSSupport)
  90. {
  91. /* PHS Sepcific */
  92. UINT unPHSPktHdrBytesCopied = 0;
  93. UINT unPhsOldHdrSize = 0;
  94. UINT unPHSNewPktHeaderLen = 0;
  95. /* Pointer to PHS IN Hdr Buffer */
  96. PUCHAR pucPHSPktHdrInBuf =
  97. Adapter->stPhsTxContextInfo.ucaHdrSuppressionInBuf;
  98. /* Pointer to PHS OUT Hdr Buffer */
  99. PUCHAR pucPHSPktHdrOutBuf =
  100. Adapter->stPhsTxContextInfo.ucaHdrSuppressionOutBuf;
  101. UINT usPacketType;
  102. UINT BytesToRemove = 0;
  103. bool bPHSI = 0;
  104. LONG ulPhsStatus = 0;
  105. UINT numBytesCompressed = 0;
  106. struct sk_buff *newPacket = NULL;
  107. struct sk_buff *Packet = *pPacket;
  108. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
  109. "In PHSTransmit");
  110. if (!bEthCSSupport)
  111. BytesToRemove = ETH_HLEN;
  112. /*
  113. * Accumulate the header upto the size we support suppression
  114. * from NDIS packet
  115. */
  116. usPacketType = ((struct ethhdr *)(Packet->data))->h_proto;
  117. pucPHSPktHdrInBuf = Packet->data + BytesToRemove;
  118. /* considering data after ethernet header */
  119. if ((*PacketLen - BytesToRemove) < MAX_PHS_LENGTHS)
  120. unPHSPktHdrBytesCopied = (*PacketLen - BytesToRemove);
  121. else
  122. unPHSPktHdrBytesCopied = MAX_PHS_LENGTHS;
  123. if ((unPHSPktHdrBytesCopied > 0) &&
  124. (unPHSPktHdrBytesCopied <= MAX_PHS_LENGTHS)) {
  125. /*
  126. * Step 2 Suppress Header using PHS and fill into intermediate
  127. * ucaPHSPktHdrOutBuf.
  128. * Suppress only if IP Header and PHS Enabled For the
  129. * Service Flow
  130. */
  131. if (((usPacketType == ETHERNET_FRAMETYPE_IPV4) ||
  132. (usPacketType == ETHERNET_FRAMETYPE_IPV6)) &&
  133. (bHeaderSuppressionEnabled)) {
  134. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND,
  135. DBG_LVL_ALL,
  136. "\nTrying to PHS Compress Using Classifier rule 0x%X",
  137. uiClassifierRuleID);
  138. unPHSNewPktHeaderLen = unPHSPktHdrBytesCopied;
  139. ulPhsStatus = PhsCompress(&Adapter->stBCMPhsContext,
  140. Vcid,
  141. uiClassifierRuleID,
  142. pucPHSPktHdrInBuf,
  143. pucPHSPktHdrOutBuf,
  144. &unPhsOldHdrSize,
  145. &unPHSNewPktHeaderLen);
  146. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND,
  147. DBG_LVL_ALL,
  148. "\nPHS Old header Size : %d New Header Size %d\n",
  149. unPhsOldHdrSize, unPHSNewPktHeaderLen);
  150. if (unPHSNewPktHeaderLen == unPhsOldHdrSize) {
  151. if (ulPhsStatus == STATUS_PHS_COMPRESSED)
  152. bPHSI = *pucPHSPktHdrOutBuf;
  153. ulPhsStatus = STATUS_PHS_NOCOMPRESSION;
  154. }
  155. if (ulPhsStatus == STATUS_PHS_COMPRESSED) {
  156. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
  157. PHS_SEND, DBG_LVL_ALL,
  158. "PHS Sending packet Compressed");
  159. if (skb_cloned(Packet)) {
  160. newPacket =
  161. skb_copy(Packet, GFP_ATOMIC);
  162. if (newPacket == NULL)
  163. return STATUS_FAILURE;
  164. dev_kfree_skb(Packet);
  165. *pPacket = Packet = newPacket;
  166. pucPHSPktHdrInBuf =
  167. Packet->data + BytesToRemove;
  168. }
  169. numBytesCompressed = unPhsOldHdrSize -
  170. (unPHSNewPktHeaderLen + PHSI_LEN);
  171. memcpy(pucPHSPktHdrInBuf + numBytesCompressed,
  172. pucPHSPktHdrOutBuf,
  173. unPHSNewPktHeaderLen + PHSI_LEN);
  174. memcpy(Packet->data + numBytesCompressed,
  175. Packet->data, BytesToRemove);
  176. skb_pull(Packet, numBytesCompressed);
  177. return STATUS_SUCCESS;
  178. } else {
  179. /* if one byte headroom is not available,
  180. * increase it through skb_cow
  181. */
  182. if (!(skb_headroom(Packet) > 0)) {
  183. if (skb_cow(Packet, 1)) {
  184. BCM_DEBUG_PRINT(Adapter,
  185. DBG_TYPE_PRINTK,
  186. 0, 0,
  187. "SKB Cow Failed\n");
  188. return STATUS_FAILURE;
  189. }
  190. }
  191. skb_push(Packet, 1);
  192. /*
  193. * CAUTION: The MAC Header is getting corrupted
  194. * here for IP CS - can be saved by copying 14
  195. * Bytes. not needed .... hence corrupting it.
  196. */
  197. *(Packet->data + BytesToRemove) = bPHSI;
  198. return STATUS_SUCCESS;
  199. }
  200. } else {
  201. if (!bHeaderSuppressionEnabled)
  202. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS,
  203. PHS_SEND, DBG_LVL_ALL,
  204. "\nHeader Suppression Disabled For SF: No PHS\n");
  205. return STATUS_SUCCESS;
  206. }
  207. }
  208. /* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
  209. * "PHSTransmit : Dumping data packet After PHS"); */
  210. return STATUS_SUCCESS;
  211. }
  212. int PHSReceive(struct bcm_mini_adapter *Adapter,
  213. USHORT usVcid,
  214. struct sk_buff *packet,
  215. UINT *punPacketLen,
  216. UCHAR *pucEthernetHdr,
  217. UINT bHeaderSuppressionEnabled)
  218. {
  219. u32 nStandardPktHdrLen = 0;
  220. u32 nTotalsuppressedPktHdrBytes = 0;
  221. int ulPhsStatus = 0;
  222. PUCHAR pucInBuff = NULL;
  223. UINT TotalBytesAdded = 0;
  224. if (!bHeaderSuppressionEnabled) {
  225. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE,
  226. DBG_LVL_ALL,
  227. "\nPhs Disabled for incoming packet");
  228. return ulPhsStatus;
  229. }
  230. pucInBuff = packet->data;
  231. /* Restore PHS suppressed header */
  232. nStandardPktHdrLen = packet->len;
  233. ulPhsStatus = PhsDeCompress(&Adapter->stBCMPhsContext,
  234. usVcid,
  235. pucInBuff,
  236. Adapter->ucaPHSPktRestoreBuf,
  237. &nTotalsuppressedPktHdrBytes,
  238. &nStandardPktHdrLen);
  239. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL,
  240. "\nSuppressed PktHdrLen : 0x%x Restored PktHdrLen : 0x%x",
  241. nTotalsuppressedPktHdrBytes, nStandardPktHdrLen);
  242. if (ulPhsStatus != STATUS_PHS_COMPRESSED) {
  243. skb_pull(packet, 1);
  244. return STATUS_SUCCESS;
  245. } else {
  246. TotalBytesAdded = nStandardPktHdrLen -
  247. nTotalsuppressedPktHdrBytes - PHSI_LEN;
  248. if (TotalBytesAdded) {
  249. if (skb_headroom(packet) >= (SKB_RESERVE_ETHERNET_HEADER + TotalBytesAdded))
  250. skb_push(packet, TotalBytesAdded);
  251. else {
  252. if (skb_cow(packet, skb_headroom(packet) + TotalBytesAdded)) {
  253. BCM_DEBUG_PRINT(Adapter,
  254. DBG_TYPE_PRINTK, 0, 0,
  255. "cow failed in receive\n");
  256. return STATUS_FAILURE;
  257. }
  258. skb_push(packet, TotalBytesAdded);
  259. }
  260. }
  261. memcpy(packet->data, Adapter->ucaPHSPktRestoreBuf,
  262. nStandardPktHdrLen);
  263. }
  264. return STATUS_SUCCESS;
  265. }
  266. void DumpFullPacket(UCHAR *pBuf, UINT nPktLen)
  267. {
  268. struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
  269. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,
  270. "Dumping Data Packet");
  271. BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,
  272. pBuf, nPktLen);
  273. }
  274. /*
  275. * Procedure: phs_init
  276. *
  277. * Description: This routine is responsible for allocating memory for classifier
  278. * and PHS rules.
  279. *
  280. * Arguments:
  281. * pPhsdeviceExtension - ptr to Device extension containing PHS Classifier rules
  282. * and PHS Rules , RX, TX buffer etc
  283. *
  284. * Returns:
  285. * TRUE(1) -If allocation of memory was successful.
  286. * FALSE -If allocation of memory fails.
  287. */
  288. int phs_init(struct bcm_phs_extension *pPhsdeviceExtension,
  289. struct bcm_mini_adapter *Adapter)
  290. {
  291. int i;
  292. struct bcm_phs_table *pstServiceFlowTable;
  293. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
  294. "\nPHS:phs_init function");
  295. if (pPhsdeviceExtension->pstServiceFlowPhsRulesTable)
  296. return -EINVAL;
  297. pPhsdeviceExtension->pstServiceFlowPhsRulesTable =
  298. kzalloc(sizeof(struct bcm_phs_table), GFP_KERNEL);
  299. if (!pPhsdeviceExtension->pstServiceFlowPhsRulesTable) {
  300. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
  301. DBG_LVL_ALL,
  302. "\nAllocation ServiceFlowPhsRulesTable failed");
  303. return -ENOMEM;
  304. }
  305. pstServiceFlowTable = pPhsdeviceExtension->pstServiceFlowPhsRulesTable;
  306. for (i = 0; i < MAX_SERVICEFLOWS; i++) {
  307. struct bcm_phs_entry sServiceFlow =
  308. pstServiceFlowTable->stSFList[i];
  309. sServiceFlow.pstClassifierTable =
  310. kzalloc(sizeof(struct bcm_phs_classifier_table),
  311. GFP_KERNEL);
  312. if (!sServiceFlow.pstClassifierTable) {
  313. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
  314. DBG_LVL_ALL, "\nAllocation failed");
  315. free_phs_serviceflow_rules(pPhsdeviceExtension->pstServiceFlowPhsRulesTable);
  316. pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL;
  317. return -ENOMEM;
  318. }
  319. }
  320. pPhsdeviceExtension->CompressedTxBuffer = kmalloc(PHS_BUFFER_SIZE, GFP_KERNEL);
  321. if (pPhsdeviceExtension->CompressedTxBuffer == NULL) {
  322. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
  323. DBG_LVL_ALL, "\nAllocation failed");
  324. free_phs_serviceflow_rules(pPhsdeviceExtension->pstServiceFlowPhsRulesTable);
  325. pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL;
  326. return -ENOMEM;
  327. }
  328. pPhsdeviceExtension->UnCompressedRxBuffer =
  329. kmalloc(PHS_BUFFER_SIZE, GFP_KERNEL);
  330. if (pPhsdeviceExtension->UnCompressedRxBuffer == NULL) {
  331. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
  332. DBG_LVL_ALL, "\nAllocation failed");
  333. kfree(pPhsdeviceExtension->CompressedTxBuffer);
  334. free_phs_serviceflow_rules(pPhsdeviceExtension->pstServiceFlowPhsRulesTable);
  335. pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL;
  336. return -ENOMEM;
  337. }
  338. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
  339. "\n phs_init Successful");
  340. return STATUS_SUCCESS;
  341. }
  342. int PhsCleanup(IN struct bcm_phs_extension *pPHSDeviceExt)
  343. {
  344. if (pPHSDeviceExt->pstServiceFlowPhsRulesTable) {
  345. free_phs_serviceflow_rules(pPHSDeviceExt->pstServiceFlowPhsRulesTable);
  346. pPHSDeviceExt->pstServiceFlowPhsRulesTable = NULL;
  347. }
  348. kfree(pPHSDeviceExt->CompressedTxBuffer);
  349. pPHSDeviceExt->CompressedTxBuffer = NULL;
  350. kfree(pPHSDeviceExt->UnCompressedRxBuffer);
  351. pPHSDeviceExt->UnCompressedRxBuffer = NULL;
  352. return 0;
  353. }
  354. /*
  355. * PHS functions
  356. * PhsUpdateClassifierRule
  357. *
  358. * Routine Description:
  359. * Exported function to add or modify a PHS Rule.
  360. *
  361. * Arguments:
  362. * IN void* pvContext - PHS Driver Specific Context
  363. * IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rule applies
  364. * IN B_UINT16 uiClsId - The Classifier ID within the Service Flow for which the PHS rule applies.
  365. * IN struct bcm_phs_rule *psPhsRule - The PHS Rule strcuture to be added to the PHS Rule table.
  366. *
  367. * Return Value:
  368. *
  369. * 0 if successful,
  370. * >0 Error.
  371. */
  372. ULONG PhsUpdateClassifierRule(IN void *pvContext,
  373. IN B_UINT16 uiVcid ,
  374. IN B_UINT16 uiClsId ,
  375. IN struct bcm_phs_rule *psPhsRule,
  376. IN B_UINT8 u8AssociatedPHSI)
  377. {
  378. ULONG lStatus = 0;
  379. UINT nSFIndex = 0;
  380. struct bcm_phs_entry *pstServiceFlowEntry = NULL;
  381. struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
  382. struct bcm_phs_extension *pDeviceExtension =
  383. (struct bcm_phs_extension *)pvContext;
  384. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
  385. "PHS With Corr2 Changes\n");
  386. if (pDeviceExtension == NULL) {
  387. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
  388. DBG_LVL_ALL, "Invalid Device Extension\n");
  389. return ERR_PHS_INVALID_DEVICE_EXETENSION;
  390. }
  391. if (u8AssociatedPHSI == 0)
  392. return ERR_PHS_INVALID_PHS_RULE;
  393. /* Retrieve the SFID Entry Index for requested Service Flow */
  394. nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
  395. uiVcid, &pstServiceFlowEntry);
  396. if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
  397. /* This is a new SF. Create a mapping entry for this */
  398. lStatus = CreateSFToClassifierRuleMapping(uiVcid, uiClsId,
  399. pDeviceExtension->pstServiceFlowPhsRulesTable,
  400. psPhsRule,
  401. u8AssociatedPHSI);
  402. return lStatus;
  403. }
  404. /* SF already Exists Add PHS Rule to existing SF */
  405. lStatus = CreateClassiferToPHSRuleMapping(uiVcid, uiClsId,
  406. pstServiceFlowEntry,
  407. psPhsRule,
  408. u8AssociatedPHSI);
  409. return lStatus;
  410. }
  411. /*
  412. * PhsDeletePHSRule
  413. *
  414. * Routine Description:
  415. * Deletes the specified phs Rule within Vcid
  416. *
  417. * Arguments:
  418. * IN void* pvContext - PHS Driver Specific Context
  419. * IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rule applies
  420. * IN B_UINT8 u8PHSI - the PHS Index identifying PHS rule to be deleted.
  421. *
  422. * Return Value:
  423. *
  424. * 0 if successful,
  425. * >0 Error.
  426. */
  427. ULONG PhsDeletePHSRule(IN void *pvContext,
  428. IN B_UINT16 uiVcid,
  429. IN B_UINT8 u8PHSI)
  430. {
  431. UINT nSFIndex = 0, nClsidIndex = 0;
  432. struct bcm_phs_entry *pstServiceFlowEntry = NULL;
  433. struct bcm_phs_classifier_table *pstClassifierRulesTable = NULL;
  434. struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
  435. struct bcm_phs_extension *pDeviceExtension = (struct bcm_phs_extension *)pvContext;
  436. struct bcm_phs_classifier_entry *curr_entry;
  437. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
  438. "======>\n");
  439. if (pDeviceExtension) {
  440. /* Retrieve the SFID Entry Index for requested Service Flow */
  441. nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
  442. uiVcid, &pstServiceFlowEntry);
  443. if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
  444. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
  445. DBG_LVL_ALL, "SFID Match Failed\n");
  446. return ERR_SF_MATCH_FAIL;
  447. }
  448. pstClassifierRulesTable = pstServiceFlowEntry->pstClassifierTable;
  449. if (pstClassifierRulesTable) {
  450. for (nClsidIndex = 0; nClsidIndex < MAX_PHSRULE_PER_SF; nClsidIndex++) {
  451. curr_entry = &pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex];
  452. if (curr_entry->bUsed &&
  453. curr_entry->pstPhsRule &&
  454. (curr_entry->pstPhsRule->u8PHSI == u8PHSI)) {
  455. if (curr_entry->pstPhsRule->u8RefCnt)
  456. curr_entry->pstPhsRule->u8RefCnt--;
  457. if (0 == curr_entry->pstPhsRule->u8RefCnt)
  458. kfree(curr_entry->pstPhsRule);
  459. memset(curr_entry,
  460. 0,
  461. sizeof(struct bcm_phs_classifier_entry));
  462. }
  463. }
  464. }
  465. }
  466. return 0;
  467. }
  468. /*
  469. * PhsDeleteClassifierRule
  470. *
  471. * Routine Description:
  472. * Exported function to Delete a PHS Rule for the SFID,CLSID Pair.
  473. *
  474. * Arguments:
  475. * IN void* pvContext - PHS Driver Specific Context
  476. * IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rule applies
  477. * IN B_UINT16 uiClsId - The Classifier ID within the Service Flow for which the PHS rule applies.
  478. *
  479. * Return Value:
  480. *
  481. * 0 if successful,
  482. * >0 Error.
  483. */
  484. ULONG PhsDeleteClassifierRule(IN void *pvContext,
  485. IN B_UINT16 uiVcid,
  486. IN B_UINT16 uiClsId)
  487. {
  488. UINT nSFIndex = 0, nClsidIndex = 0;
  489. struct bcm_phs_entry *pstServiceFlowEntry = NULL;
  490. struct bcm_phs_classifier_entry *pstClassifierEntry = NULL;
  491. struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
  492. struct bcm_phs_extension *pDeviceExtension =
  493. (struct bcm_phs_extension *)pvContext;
  494. if (!pDeviceExtension)
  495. goto out;
  496. /* Retrieve the SFID Entry Index for requested Service Flow */
  497. nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
  498. uiVcid, &pstServiceFlowEntry);
  499. if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
  500. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
  501. DBG_LVL_ALL, "SFID Match Failed\n");
  502. return ERR_SF_MATCH_FAIL;
  503. }
  504. nClsidIndex =
  505. GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable,
  506. uiClsId,
  507. eActiveClassifierRuleContext,
  508. &pstClassifierEntry);
  509. if ((nClsidIndex != PHS_INVALID_TABLE_INDEX) &&
  510. (!pstClassifierEntry->bUnclassifiedPHSRule)) {
  511. if (pstClassifierEntry->pstPhsRule) {
  512. if (pstClassifierEntry->pstPhsRule->u8RefCnt)
  513. pstClassifierEntry->pstPhsRule->u8RefCnt--;
  514. if (0 == pstClassifierEntry->pstPhsRule->u8RefCnt)
  515. kfree(pstClassifierEntry->pstPhsRule);
  516. }
  517. memset(pstClassifierEntry, 0,
  518. sizeof(struct bcm_phs_classifier_entry));
  519. }
  520. nClsidIndex =
  521. GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable,
  522. uiClsId,
  523. eOldClassifierRuleContext,
  524. &pstClassifierEntry);
  525. if ((nClsidIndex != PHS_INVALID_TABLE_INDEX) &&
  526. (!pstClassifierEntry->bUnclassifiedPHSRule)) {
  527. kfree(pstClassifierEntry->pstPhsRule);
  528. memset(pstClassifierEntry, 0,
  529. sizeof(struct bcm_phs_classifier_entry));
  530. }
  531. out:
  532. return 0;
  533. }
  534. /*
  535. * PhsDeleteSFRules
  536. *
  537. * Routine Description:
  538. * Exported function to Delete a all PHS Rules for the SFID.
  539. *
  540. * Arguments:
  541. * IN void* pvContext - PHS Driver Specific Context
  542. * IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rules need to be deleted
  543. *
  544. * Return Value:
  545. *
  546. * 0 if successful,
  547. * >0 Error.
  548. */
  549. ULONG PhsDeleteSFRules(IN void *pvContext, IN B_UINT16 uiVcid)
  550. {
  551. UINT nSFIndex = 0, nClsidIndex = 0;
  552. struct bcm_phs_entry *pstServiceFlowEntry = NULL;
  553. struct bcm_phs_classifier_table *pstClassifierRulesTable = NULL;
  554. struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
  555. struct bcm_phs_extension *pDeviceExtension =
  556. (struct bcm_phs_extension *)pvContext;
  557. struct bcm_phs_classifier_entry *curr_clsf_entry;
  558. struct bcm_phs_classifier_entry *curr_rules_list;
  559. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
  560. "====>\n");
  561. if (!pDeviceExtension)
  562. goto out;
  563. /* Retrieve the SFID Entry Index for requested Service Flow */
  564. nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
  565. uiVcid, &pstServiceFlowEntry);
  566. if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
  567. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
  568. DBG_LVL_ALL, "SFID Match Failed\n");
  569. return ERR_SF_MATCH_FAIL;
  570. }
  571. pstClassifierRulesTable = pstServiceFlowEntry->pstClassifierTable;
  572. if (pstClassifierRulesTable) {
  573. for (nClsidIndex = 0; nClsidIndex < MAX_PHSRULE_PER_SF; nClsidIndex++) {
  574. curr_clsf_entry =
  575. &pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex];
  576. curr_rules_list =
  577. &pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex];
  578. if (curr_clsf_entry->pstPhsRule) {
  579. if (curr_clsf_entry->pstPhsRule->u8RefCnt)
  580. curr_clsf_entry->pstPhsRule->u8RefCnt--;
  581. if (0 == curr_clsf_entry->pstPhsRule->u8RefCnt)
  582. kfree(curr_clsf_entry->pstPhsRule);
  583. curr_clsf_entry->pstPhsRule = NULL;
  584. }
  585. memset(curr_clsf_entry, 0,
  586. sizeof(struct bcm_phs_classifier_entry));
  587. if (curr_rules_list->pstPhsRule) {
  588. if (curr_rules_list->pstPhsRule->u8RefCnt)
  589. curr_rules_list->pstPhsRule->u8RefCnt--;
  590. if (0 == curr_rules_list->pstPhsRule->u8RefCnt)
  591. kfree(curr_rules_list->pstPhsRule);
  592. curr_rules_list->pstPhsRule = NULL;
  593. }
  594. memset(curr_rules_list, 0,
  595. sizeof(struct bcm_phs_classifier_entry));
  596. }
  597. }
  598. pstServiceFlowEntry->bUsed = false;
  599. pstServiceFlowEntry->uiVcid = 0;
  600. out:
  601. return 0;
  602. }
  603. /*
  604. * PhsCompress
  605. *
  606. * Routine Description:
  607. * Exported function to compress the data using PHS.
  608. *
  609. * Arguments:
  610. * IN void* pvContext - PHS Driver Specific Context.
  611. * IN B_UINT16 uiVcid - The Service Flow ID to which current
  612. * packet header compression applies.
  613. * IN UINT uiClsId - The Classifier ID to which current packet
  614. * header compression applies.
  615. * IN void *pvInputBuffer - The Input buffer containg packet header
  616. * data
  617. * IN void *pvOutputBuffer - The output buffer returned by this
  618. * function after PHS
  619. * IN UINT *pOldHeaderSize - The actual size of the header before PHS
  620. * IN UINT *pNewHeaderSize - The new size of the header after applying
  621. * PHS
  622. *
  623. * Return Value:
  624. *
  625. * 0 if successful,
  626. * >0 Error.
  627. */
  628. static ULONG PhsCompress(IN void *pvContext,
  629. IN B_UINT16 uiVcid,
  630. IN B_UINT16 uiClsId,
  631. IN void *pvInputBuffer,
  632. OUT void *pvOutputBuffer,
  633. OUT UINT *pOldHeaderSize,
  634. OUT UINT *pNewHeaderSize)
  635. {
  636. UINT nSFIndex = 0, nClsidIndex = 0;
  637. struct bcm_phs_entry *pstServiceFlowEntry = NULL;
  638. struct bcm_phs_classifier_entry *pstClassifierEntry = NULL;
  639. struct bcm_phs_rule *pstPhsRule = NULL;
  640. ULONG lStatus = 0;
  641. struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
  642. struct bcm_phs_extension *pDeviceExtension =
  643. (struct bcm_phs_extension *)pvContext;
  644. if (pDeviceExtension == NULL) {
  645. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
  646. "Invalid Device Extension\n");
  647. lStatus = STATUS_PHS_NOCOMPRESSION;
  648. return lStatus;
  649. }
  650. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
  651. "Suppressing header\n");
  652. /* Retrieve the SFID Entry Index for requested Service Flow */
  653. nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
  654. uiVcid, &pstServiceFlowEntry);
  655. if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
  656. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
  657. "SFID Match Failed\n");
  658. lStatus = STATUS_PHS_NOCOMPRESSION;
  659. return lStatus;
  660. }
  661. nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable,
  662. uiClsId, eActiveClassifierRuleContext,
  663. &pstClassifierEntry);
  664. if (nClsidIndex == PHS_INVALID_TABLE_INDEX) {
  665. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
  666. "No PHS Rule Defined For Classifier\n");
  667. lStatus = STATUS_PHS_NOCOMPRESSION;
  668. return lStatus;
  669. }
  670. /* get rule from SF id,Cls ID pair and proceed */
  671. pstPhsRule = pstClassifierEntry->pstPhsRule;
  672. if (!ValidatePHSRuleComplete(pstPhsRule)) {
  673. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
  674. "PHS Rule Defined For Classifier But Not Complete\n");
  675. lStatus = STATUS_PHS_NOCOMPRESSION;
  676. return lStatus;
  677. }
  678. /* Compress Packet */
  679. lStatus = phs_compress(pstPhsRule,
  680. (PUCHAR)pvInputBuffer,
  681. (PUCHAR)pvOutputBuffer,
  682. pOldHeaderSize,
  683. pNewHeaderSize);
  684. if (lStatus == STATUS_PHS_COMPRESSED) {
  685. pstPhsRule->PHSModifiedBytes +=
  686. *pOldHeaderSize - *pNewHeaderSize - 1;
  687. pstPhsRule->PHSModifiedNumPackets++;
  688. } else {
  689. pstPhsRule->PHSErrorNumPackets++;
  690. }
  691. return lStatus;
  692. }
  693. /*
  694. * PhsDeCompress
  695. *
  696. * Routine Description:
  697. * Exported function to restore the packet header in Rx path.
  698. *
  699. * Arguments:
  700. * IN void* pvContext - PHS Driver Specific Context.
  701. * IN B_UINT16 uiVcid - The Service Flow ID to which current
  702. * packet header restoration applies.
  703. * IN void *pvInputBuffer - The Input buffer containg suppressed
  704. * packet header data
  705. * OUT void *pvOutputBuffer - The output buffer returned by this
  706. * function after restoration
  707. * OUT UINT *pHeaderSize - The packet header size after restoration
  708. * is returned in this parameter.
  709. *
  710. * Return Value:
  711. *
  712. * 0 if successful,
  713. * >0 Error.
  714. */
  715. static ULONG PhsDeCompress(IN void *pvContext,
  716. IN B_UINT16 uiVcid,
  717. IN void *pvInputBuffer,
  718. OUT void *pvOutputBuffer,
  719. OUT UINT *pInHeaderSize,
  720. OUT UINT *pOutHeaderSize)
  721. {
  722. UINT nSFIndex = 0, nPhsRuleIndex = 0;
  723. struct bcm_phs_entry *pstServiceFlowEntry = NULL;
  724. struct bcm_phs_rule *pstPhsRule = NULL;
  725. UINT phsi;
  726. struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
  727. struct bcm_phs_extension *pDeviceExtension =
  728. (struct bcm_phs_extension *)pvContext;
  729. *pInHeaderSize = 0;
  730. if (pDeviceExtension == NULL) {
  731. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE,
  732. DBG_LVL_ALL, "Invalid Device Extension\n");
  733. return ERR_PHS_INVALID_DEVICE_EXETENSION;
  734. }
  735. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL,
  736. "Restoring header\n");
  737. phsi = *((unsigned char *)(pvInputBuffer));
  738. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL,
  739. "PHSI To Be Used For restore : %x\n", phsi);
  740. if (phsi == UNCOMPRESSED_PACKET)
  741. return STATUS_PHS_NOCOMPRESSION;
  742. /* Retrieve the SFID Entry Index for requested Service Flow */
  743. nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable,
  744. uiVcid, &pstServiceFlowEntry);
  745. if (nSFIndex == PHS_INVALID_TABLE_INDEX) {
  746. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE,
  747. DBG_LVL_ALL,
  748. "SFID Match Failed During Lookup\n");
  749. return ERR_SF_MATCH_FAIL;
  750. }
  751. nPhsRuleIndex = GetPhsRuleEntry(pstServiceFlowEntry->pstClassifierTable,
  752. phsi,
  753. eActiveClassifierRuleContext,
  754. &pstPhsRule);
  755. if (nPhsRuleIndex == PHS_INVALID_TABLE_INDEX) {
  756. /* Phs Rule does not exist in active rules table. Lets try
  757. * in the old rules table. */
  758. nPhsRuleIndex = GetPhsRuleEntry(pstServiceFlowEntry->pstClassifierTable,
  759. phsi,
  760. eOldClassifierRuleContext,
  761. &pstPhsRule);
  762. if (nPhsRuleIndex == PHS_INVALID_TABLE_INDEX)
  763. return ERR_PHSRULE_MATCH_FAIL;
  764. }
  765. *pInHeaderSize = phs_decompress((PUCHAR)pvInputBuffer,
  766. (PUCHAR)pvOutputBuffer,
  767. pstPhsRule,
  768. pOutHeaderSize);
  769. pstPhsRule->PHSModifiedBytes += *pOutHeaderSize - *pInHeaderSize - 1;
  770. pstPhsRule->PHSModifiedNumPackets++;
  771. return STATUS_PHS_COMPRESSED;
  772. }
  773. /*
  774. * Procedure: free_phs_serviceflow_rules
  775. *
  776. * Description: This routine is responsible for freeing memory allocated for
  777. * PHS rules.
  778. *
  779. * Arguments:
  780. * rules - ptr to S_SERVICEFLOW_TABLE structure.
  781. *
  782. * Returns:
  783. * Does not return any value.
  784. */
  785. static void free_phs_serviceflow_rules(struct bcm_phs_table *psServiceFlowRulesTable)
  786. {
  787. int i, j;
  788. struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
  789. struct bcm_phs_classifier_entry *curr_act_rules_list;
  790. struct bcm_phs_classifier_entry *curr_old_rules_list;
  791. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
  792. "=======>\n");
  793. if (!psServiceFlowRulesTable)
  794. goto out;
  795. for (i = 0; i < MAX_SERVICEFLOWS; i++) {
  796. struct bcm_phs_entry stServiceFlowEntry =
  797. psServiceFlowRulesTable->stSFList[i];
  798. struct bcm_phs_classifier_table *pstClassifierRulesTable =
  799. stServiceFlowEntry.pstClassifierTable;
  800. if (pstClassifierRulesTable) {
  801. for (j = 0; j < MAX_PHSRULE_PER_SF; j++) {
  802. curr_act_rules_list =
  803. &pstClassifierRulesTable->stActivePhsRulesList[j];
  804. curr_old_rules_list =
  805. &pstClassifierRulesTable->stOldPhsRulesList[j];
  806. if (curr_act_rules_list->pstPhsRule) {
  807. if (curr_act_rules_list->pstPhsRule->u8RefCnt)
  808. curr_act_rules_list->pstPhsRule->u8RefCnt--;
  809. if (0 == curr_act_rules_list->pstPhsRule->u8RefCnt)
  810. kfree(curr_act_rules_list->pstPhsRule);
  811. curr_act_rules_list->pstPhsRule = NULL;
  812. }
  813. if (curr_old_rules_list->pstPhsRule) {
  814. if (curr_old_rules_list->pstPhsRule->u8RefCnt)
  815. curr_old_rules_list->pstPhsRule->u8RefCnt--;
  816. if (0 == curr_old_rules_list->pstPhsRule->u8RefCnt)
  817. kfree(curr_old_rules_list->pstPhsRule);
  818. curr_old_rules_list->pstPhsRule = NULL;
  819. }
  820. }
  821. kfree(pstClassifierRulesTable);
  822. stServiceFlowEntry.pstClassifierTable =
  823. pstClassifierRulesTable = NULL;
  824. }
  825. }
  826. out:
  827. kfree(psServiceFlowRulesTable);
  828. psServiceFlowRulesTable = NULL;
  829. }
  830. static bool ValidatePHSRuleComplete(IN const struct bcm_phs_rule *psPhsRule)
  831. {
  832. return (psPhsRule &&
  833. psPhsRule->u8PHSI &&
  834. psPhsRule->u8PHSS &&
  835. psPhsRule->u8PHSFLength);
  836. }
  837. UINT GetServiceFlowEntry(IN struct bcm_phs_table *psServiceFlowTable,
  838. IN B_UINT16 uiVcid,
  839. struct bcm_phs_entry **ppstServiceFlowEntry)
  840. {
  841. int i;
  842. struct bcm_phs_entry *curr_sf_list;
  843. for (i = 0; i < MAX_SERVICEFLOWS; i++) {
  844. curr_sf_list = &psServiceFlowTable->stSFList[i];
  845. if (curr_sf_list->bUsed && (curr_sf_list->uiVcid == uiVcid)) {
  846. *ppstServiceFlowEntry = curr_sf_list;
  847. return i;
  848. }
  849. }
  850. *ppstServiceFlowEntry = NULL;
  851. return PHS_INVALID_TABLE_INDEX;
  852. }
  853. static UINT GetClassifierEntry(IN struct bcm_phs_classifier_table *pstClassifierTable,
  854. IN B_UINT32 uiClsid,
  855. enum bcm_phs_classifier_context eClsContext,
  856. OUT struct bcm_phs_classifier_entry **ppstClassifierEntry)
  857. {
  858. int i;
  859. struct bcm_phs_classifier_entry *psClassifierRules = NULL;
  860. for (i = 0; i < MAX_PHSRULE_PER_SF; i++) {
  861. if (eClsContext == eActiveClassifierRuleContext)
  862. psClassifierRules =
  863. &pstClassifierTable->stActivePhsRulesList[i];
  864. else
  865. psClassifierRules =
  866. &pstClassifierTable->stOldPhsRulesList[i];
  867. if (psClassifierRules->bUsed &&
  868. (psClassifierRules->uiClassifierRuleId == uiClsid)) {
  869. *ppstClassifierEntry = psClassifierRules;
  870. return i;
  871. }
  872. }
  873. *ppstClassifierEntry = NULL;
  874. return PHS_INVALID_TABLE_INDEX;
  875. }
  876. static UINT GetPhsRuleEntry(IN struct bcm_phs_classifier_table *pstClassifierTable,
  877. IN B_UINT32 uiPHSI,
  878. enum bcm_phs_classifier_context eClsContext,
  879. OUT struct bcm_phs_rule **ppstPhsRule)
  880. {
  881. int i;
  882. struct bcm_phs_classifier_entry *pstClassifierRule = NULL;
  883. for (i = 0; i < MAX_PHSRULE_PER_SF; i++) {
  884. if (eClsContext == eActiveClassifierRuleContext)
  885. pstClassifierRule =
  886. &pstClassifierTable->stActivePhsRulesList[i];
  887. else
  888. pstClassifierRule =
  889. &pstClassifierTable->stOldPhsRulesList[i];
  890. if (pstClassifierRule->bUsed &&
  891. (pstClassifierRule->u8PHSI == uiPHSI)) {
  892. *ppstPhsRule = pstClassifierRule->pstPhsRule;
  893. return i;
  894. }
  895. }
  896. *ppstPhsRule = NULL;
  897. return PHS_INVALID_TABLE_INDEX;
  898. }
  899. static UINT CreateSFToClassifierRuleMapping(IN B_UINT16 uiVcid,
  900. IN B_UINT16 uiClsId,
  901. IN struct bcm_phs_table *psServiceFlowTable,
  902. struct bcm_phs_rule *psPhsRule,
  903. B_UINT8 u8AssociatedPHSI)
  904. {
  905. struct bcm_phs_classifier_table *psaClassifiertable = NULL;
  906. UINT uiStatus = 0;
  907. int iSfIndex;
  908. bool bFreeEntryFound = false;
  909. struct bcm_phs_entry *curr_list;
  910. /* Check for a free entry in SFID table */
  911. for (iSfIndex = 0; iSfIndex < MAX_SERVICEFLOWS; iSfIndex++) {
  912. curr_list = &psServiceFlowTable->stSFList[iSfIndex];
  913. if (!curr_list->bUsed) {
  914. bFreeEntryFound = TRUE;
  915. break;
  916. }
  917. }
  918. if (!bFreeEntryFound)
  919. return ERR_SFTABLE_FULL;
  920. psaClassifiertable = curr_list->pstClassifierTable;
  921. uiStatus = CreateClassifierPHSRule(uiClsId,
  922. psaClassifiertable,
  923. psPhsRule,
  924. eActiveClassifierRuleContext,
  925. u8AssociatedPHSI);
  926. if (uiStatus == PHS_SUCCESS) {
  927. /* Add entry at free index to the SF */
  928. curr_list->bUsed = TRUE;
  929. curr_list->uiVcid = uiVcid;
  930. }
  931. return uiStatus;
  932. }
  933. static UINT CreateClassiferToPHSRuleMapping(IN B_UINT16 uiVcid,
  934. IN B_UINT16 uiClsId,
  935. IN struct bcm_phs_entry *pstServiceFlowEntry,
  936. struct bcm_phs_rule *psPhsRule,
  937. B_UINT8 u8AssociatedPHSI)
  938. {
  939. struct bcm_phs_classifier_entry *pstClassifierEntry = NULL;
  940. UINT uiStatus = PHS_SUCCESS;
  941. UINT nClassifierIndex = 0;
  942. struct bcm_phs_classifier_table *psaClassifiertable = NULL;
  943. struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
  944. psaClassifiertable = pstServiceFlowEntry->pstClassifierTable;
  945. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
  946. "==>");
  947. /* Check if the supplied Classifier already exists */
  948. nClassifierIndex = GetClassifierEntry(
  949. pstServiceFlowEntry->pstClassifierTable,
  950. uiClsId,
  951. eActiveClassifierRuleContext,
  952. &pstClassifierEntry);
  953. if (nClassifierIndex == PHS_INVALID_TABLE_INDEX) {
  954. /*
  955. * The Classifier doesn't exist. So its a new classifier being
  956. * added.
  957. * Add new entry to associate PHS Rule to the Classifier
  958. */
  959. uiStatus = CreateClassifierPHSRule(uiClsId, psaClassifiertable,
  960. psPhsRule,
  961. eActiveClassifierRuleContext,
  962. u8AssociatedPHSI);
  963. return uiStatus;
  964. }
  965. /*
  966. * The Classifier exists.The PHS Rule for this classifier
  967. * is being modified
  968. */
  969. if (pstClassifierEntry->u8PHSI == psPhsRule->u8PHSI) {
  970. if (pstClassifierEntry->pstPhsRule == NULL)
  971. return ERR_PHS_INVALID_PHS_RULE;
  972. /*
  973. * This rule already exists if any fields are changed for this
  974. * PHS rule update them.
  975. */
  976. /* If any part of PHSF is valid then we update PHSF */
  977. if (psPhsRule->u8PHSFLength) {
  978. /* update PHSF */
  979. memcpy(pstClassifierEntry->pstPhsRule->u8PHSF,
  980. psPhsRule->u8PHSF,
  981. MAX_PHS_LENGTHS);
  982. }
  983. if (psPhsRule->u8PHSFLength) {
  984. /* update PHSFLen */
  985. pstClassifierEntry->pstPhsRule->u8PHSFLength =
  986. psPhsRule->u8PHSFLength;
  987. }
  988. if (psPhsRule->u8PHSMLength) {
  989. /* update PHSM */
  990. memcpy(pstClassifierEntry->pstPhsRule->u8PHSM,
  991. psPhsRule->u8PHSM,
  992. MAX_PHS_LENGTHS);
  993. }
  994. if (psPhsRule->u8PHSMLength) {
  995. /* update PHSM Len */
  996. pstClassifierEntry->pstPhsRule->u8PHSMLength =
  997. psPhsRule->u8PHSMLength;
  998. }
  999. if (psPhsRule->u8PHSS) {
  1000. /* update PHSS */
  1001. pstClassifierEntry->pstPhsRule->u8PHSS =
  1002. psPhsRule->u8PHSS;
  1003. }
  1004. /* update PHSV */
  1005. pstClassifierEntry->pstPhsRule->u8PHSV = psPhsRule->u8PHSV;
  1006. } else {
  1007. /* A new rule is being set for this classifier. */
  1008. uiStatus = UpdateClassifierPHSRule(uiClsId,
  1009. pstClassifierEntry,
  1010. psaClassifiertable,
  1011. psPhsRule,
  1012. u8AssociatedPHSI);
  1013. }
  1014. return uiStatus;
  1015. }
  1016. static UINT CreateClassifierPHSRule(IN B_UINT16 uiClsId,
  1017. struct bcm_phs_classifier_table *psaClassifiertable,
  1018. struct bcm_phs_rule *psPhsRule,
  1019. enum bcm_phs_classifier_context eClsContext,
  1020. B_UINT8 u8AssociatedPHSI)
  1021. {
  1022. UINT iClassifierIndex = 0;
  1023. bool bFreeEntryFound = false;
  1024. struct bcm_phs_classifier_entry *psClassifierRules = NULL;
  1025. UINT nStatus = PHS_SUCCESS;
  1026. struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
  1027. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,
  1028. "Inside CreateClassifierPHSRule");
  1029. if (psaClassifiertable == NULL)
  1030. return ERR_INVALID_CLASSIFIERTABLE_FOR_SF;
  1031. if (eClsContext == eOldClassifierRuleContext) {
  1032. /*
  1033. * If An Old Entry for this classifier ID already exists in the
  1034. * old rules table replace it.
  1035. */
  1036. iClassifierIndex = GetClassifierEntry(psaClassifiertable,
  1037. uiClsId,
  1038. eClsContext,
  1039. &psClassifierRules);
  1040. if (iClassifierIndex != PHS_INVALID_TABLE_INDEX) {
  1041. /*
  1042. * The Classifier already exists in the old rules table
  1043. * Lets replace the old classifier with the new one.
  1044. */
  1045. bFreeEntryFound = TRUE;
  1046. }
  1047. }
  1048. if (!bFreeEntryFound) {
  1049. /* Continue to search for a free location to add the rule */
  1050. for (iClassifierIndex = 0; iClassifierIndex <
  1051. MAX_PHSRULE_PER_SF; iClassifierIndex++) {
  1052. if (eClsContext == eActiveClassifierRuleContext)
  1053. psClassifierRules = &psaClassifiertable->stActivePhsRulesList[iClassifierIndex];
  1054. else
  1055. psClassifierRules = &psaClassifiertable->stOldPhsRulesList[iClassifierIndex];
  1056. if (!psClassifierRules->bUsed) {
  1057. bFreeEntryFound = TRUE;
  1058. break;
  1059. }
  1060. }
  1061. }
  1062. if (!bFreeEntryFound) {
  1063. if (eClsContext == eActiveClassifierRuleContext)
  1064. return ERR_CLSASSIFIER_TABLE_FULL;
  1065. else {
  1066. /* Lets replace the oldest rule if we are looking in
  1067. * old Rule table */
  1068. if (psaClassifiertable->uiOldestPhsRuleIndex >= MAX_PHSRULE_PER_SF)
  1069. psaClassifiertable->uiOldestPhsRuleIndex = 0;
  1070. iClassifierIndex =
  1071. psaClassifiertable->uiOldestPhsRuleIndex;
  1072. psClassifierRules =
  1073. &psaClassifiertable->stOldPhsRulesList[iClassifierIndex];
  1074. (psaClassifiertable->uiOldestPhsRuleIndex)++;
  1075. }
  1076. }
  1077. if (eClsContext == eOldClassifierRuleContext) {
  1078. if (psClassifierRules->pstPhsRule == NULL) {
  1079. psClassifierRules->pstPhsRule =
  1080. kmalloc(sizeof(struct bcm_phs_rule),
  1081. GFP_KERNEL);
  1082. if (NULL == psClassifierRules->pstPhsRule)
  1083. return ERR_PHSRULE_MEMALLOC_FAIL;
  1084. }
  1085. psClassifierRules->bUsed = TRUE;
  1086. psClassifierRules->uiClassifierRuleId = uiClsId;
  1087. psClassifierRules->u8PHSI = psPhsRule->u8PHSI;
  1088. psClassifierRules->bUnclassifiedPHSRule =
  1089. psPhsRule->bUnclassifiedPHSRule;
  1090. /* Update The PHS rule */
  1091. memcpy(psClassifierRules->pstPhsRule, psPhsRule,
  1092. sizeof(struct bcm_phs_rule));
  1093. } else
  1094. nStatus = UpdateClassifierPHSRule(uiClsId,
  1095. psClassifierRules,
  1096. psaClassifiertable,
  1097. psPhsRule,
  1098. u8AssociatedPHSI);
  1099. return nStatus;
  1100. }
  1101. static UINT UpdateClassifierPHSRule(IN B_UINT16 uiClsId,
  1102. IN struct bcm_phs_classifier_entry *pstClassifierEntry,
  1103. struct bcm_phs_classifier_table *psaClassifiertable,
  1104. struct bcm_phs_rule *psPhsRule,
  1105. B_UINT8 u8AssociatedPHSI)
  1106. {
  1107. struct bcm_phs_rule *pstAddPhsRule = NULL;
  1108. UINT nPhsRuleIndex = 0;
  1109. bool bPHSRuleOrphaned = false;
  1110. struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
  1111. psPhsRule->u8RefCnt = 0;
  1112. /* Step 1 Deref Any Exisiting PHS Rule in this classifier Entry */
  1113. bPHSRuleOrphaned = DerefPhsRule(uiClsId, psaClassifiertable,
  1114. pstClassifierEntry->pstPhsRule);
  1115. /* Step 2 Search if there is a PHS Rule with u8AssociatedPHSI in
  1116. * Classifier table for this SF */
  1117. nPhsRuleIndex = GetPhsRuleEntry(psaClassifiertable, u8AssociatedPHSI,
  1118. eActiveClassifierRuleContext,
  1119. &pstAddPhsRule);
  1120. if (PHS_INVALID_TABLE_INDEX == nPhsRuleIndex) {
  1121. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
  1122. DBG_LVL_ALL,
  1123. "\nAdding New PHSRuleEntry For Classifier");
  1124. if (psPhsRule->u8PHSI == 0) {
  1125. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
  1126. DBG_LVL_ALL, "\nError PHSI is Zero\n");
  1127. return ERR_PHS_INVALID_PHS_RULE;
  1128. }
  1129. /* Step 2.a PHS Rule Does Not Exist .Create New PHS Rule for
  1130. * uiClsId */
  1131. if (false == bPHSRuleOrphaned) {
  1132. pstClassifierEntry->pstPhsRule =
  1133. kmalloc(sizeof(struct bcm_phs_rule),
  1134. GFP_KERNEL);
  1135. if (NULL == pstClassifierEntry->pstPhsRule)
  1136. return ERR_PHSRULE_MEMALLOC_FAIL;
  1137. }
  1138. memcpy(pstClassifierEntry->pstPhsRule, psPhsRule,
  1139. sizeof(struct bcm_phs_rule));
  1140. } else {
  1141. /* Step 2.b PHS Rule Exists Tie uiClsId with the existing
  1142. * PHS Rule */
  1143. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_DISPATCH,
  1144. DBG_LVL_ALL,
  1145. "\nTying Classifier to Existing PHS Rule");
  1146. if (bPHSRuleOrphaned) {
  1147. kfree(pstClassifierEntry->pstPhsRule);
  1148. pstClassifierEntry->pstPhsRule = NULL;
  1149. }
  1150. pstClassifierEntry->pstPhsRule = pstAddPhsRule;
  1151. }
  1152. pstClassifierEntry->bUsed = TRUE;
  1153. pstClassifierEntry->u8PHSI = pstClassifierEntry->pstPhsRule->u8PHSI;
  1154. pstClassifierEntry->uiClassifierRuleId = uiClsId;
  1155. pstClassifierEntry->pstPhsRule->u8RefCnt++;
  1156. pstClassifierEntry->bUnclassifiedPHSRule =
  1157. pstClassifierEntry->pstPhsRule->bUnclassifiedPHSRule;
  1158. return PHS_SUCCESS;
  1159. }
  1160. static bool DerefPhsRule(IN B_UINT16 uiClsId,
  1161. struct bcm_phs_classifier_table *psaClassifiertable,
  1162. struct bcm_phs_rule *pstPhsRule)
  1163. {
  1164. if (pstPhsRule == NULL)
  1165. return false;
  1166. if (pstPhsRule->u8RefCnt)
  1167. pstPhsRule->u8RefCnt--;
  1168. return (0 == pstPhsRule->u8RefCnt);
  1169. }
  1170. static void dbg_print_st_cls_entry(struct bcm_mini_adapter *ad,
  1171. struct bcm_phs_entry *st_serv_flow_entry,
  1172. struct bcm_phs_classifier_entry *st_cls_entry)
  1173. {
  1174. int k;
  1175. BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n VCID : %#X", st_serv_flow_entry->uiVcid);
  1176. BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n ClassifierID : %#X", st_cls_entry->uiClassifierRuleId);
  1177. BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSRuleID : %#X", st_cls_entry->u8PHSI);
  1178. BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n****************PHS Rule********************\n");
  1179. BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSI : %#X", st_cls_entry->pstPhsRule->u8PHSI);
  1180. BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSFLength : %#X ", st_cls_entry->pstPhsRule->u8PHSFLength);
  1181. BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSF : ");
  1182. for (k = 0 ; k < st_cls_entry->pstPhsRule->u8PHSFLength; k++)
  1183. BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "%#X ", st_cls_entry->pstPhsRule->u8PHSF[k]);
  1184. BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSMLength : %#X", st_cls_entry->pstPhsRule->u8PHSMLength);
  1185. BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSM :");
  1186. for (k = 0; k < st_cls_entry->pstPhsRule->u8PHSMLength; k++)
  1187. BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "%#X ", st_cls_entry->pstPhsRule->u8PHSM[k]);
  1188. BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSS : %#X ", st_cls_entry->pstPhsRule->u8PHSS);
  1189. BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSV : %#X", st_cls_entry->pstPhsRule->u8PHSV);
  1190. BCM_DEBUG_PRINT(ad, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n********************************************\n");
  1191. }
  1192. static void phsrules_per_sf_dbg_print(struct bcm_mini_adapter *ad,
  1193. struct bcm_phs_entry *st_serv_flow_entry)
  1194. {
  1195. int j, l;
  1196. struct bcm_phs_classifier_entry st_cls_entry;
  1197. for (j = 0; j < MAX_PHSRULE_PER_SF; j++) {
  1198. for (l = 0; l < 2; l++) {
  1199. if (l == 0) {
  1200. st_cls_entry = st_serv_flow_entry->pstClassifierTable->stActivePhsRulesList[j];
  1201. if (st_cls_entry.bUsed)
  1202. BCM_DEBUG_PRINT(ad,
  1203. DBG_TYPE_OTHERS,
  1204. DUMP_INFO,
  1205. (DBG_LVL_ALL | DBG_NO_FUNC_PRINT),
  1206. "\n Active PHS Rule :\n");
  1207. } else {
  1208. st_cls_entry = st_serv_flow_entry->pstClassifierTable->stOldPhsRulesList[j];
  1209. if (st_cls_entry.bUsed)
  1210. BCM_DEBUG_PRINT(ad,
  1211. DBG_TYPE_OTHERS,
  1212. DUMP_INFO,
  1213. (DBG_LVL_ALL | DBG_NO_FUNC_PRINT),
  1214. "\n Old PHS Rule :\n");
  1215. }
  1216. if (st_cls_entry.bUsed) {
  1217. dbg_print_st_cls_entry(ad,
  1218. st_serv_flow_entry,
  1219. &st_cls_entry);
  1220. }
  1221. }
  1222. }
  1223. }
  1224. void DumpPhsRules(struct bcm_phs_extension *pDeviceExtension)
  1225. {
  1226. int i;
  1227. struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
  1228. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,
  1229. "\n Dumping PHS Rules :\n");
  1230. for (i = 0; i < MAX_SERVICEFLOWS; i++) {
  1231. struct bcm_phs_entry stServFlowEntry =
  1232. pDeviceExtension->pstServiceFlowPhsRulesTable->stSFList[i];
  1233. if (!stServFlowEntry.bUsed)
  1234. continue;
  1235. phsrules_per_sf_dbg_print(Adapter, &stServFlowEntry);
  1236. }
  1237. }
  1238. /*
  1239. * Procedure: phs_decompress
  1240. *
  1241. * Description: This routine restores the static fields within the packet.
  1242. *
  1243. * Arguments:
  1244. * in_buf - ptr to incoming packet buffer.
  1245. * out_buf - ptr to output buffer where the suppressed
  1246. * header is copied.
  1247. * decomp_phs_rules - ptr to PHS rule.
  1248. * header_size - ptr to field which holds the phss or
  1249. * phsf_length.
  1250. *
  1251. * Returns:
  1252. * size - The number of bytes of dynamic fields present with in the
  1253. * incoming packet header.
  1254. * 0 - If PHS rule is NULL.If PHSI is 0 indicateing packet as
  1255. * uncompressed.
  1256. */
  1257. static int phs_decompress(unsigned char *in_buf,
  1258. unsigned char *out_buf,
  1259. struct bcm_phs_rule *decomp_phs_rules,
  1260. UINT *header_size)
  1261. {
  1262. int phss, size = 0;
  1263. struct bcm_phs_rule *tmp_memb;
  1264. int bit, i = 0;
  1265. unsigned char *phsf, *phsm;
  1266. int in_buf_len = *header_size - 1;
  1267. struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
  1268. in_buf++;
  1269. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE, DBG_LVL_ALL,
  1270. "====>\n");
  1271. *header_size = 0;
  1272. if (decomp_phs_rules == NULL)
  1273. return 0;
  1274. tmp_memb = decomp_phs_rules;
  1275. /*
  1276. * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,
  1277. * "\nDECOMP:In phs_decompress PHSI 1 %d",phsi));
  1278. * header_size = tmp_memb->u8PHSFLength;
  1279. */
  1280. phss = tmp_memb->u8PHSS;
  1281. phsf = tmp_memb->u8PHSF;
  1282. phsm = tmp_memb->u8PHSM;
  1283. if (phss > MAX_PHS_LENGTHS)
  1284. phss = MAX_PHS_LENGTHS;
  1285. /*
  1286. * BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECEIVE,DBG_LVL_ALL,
  1287. * "\nDECOMP:
  1288. * In phs_decompress PHSI %d phss %d index %d",phsi,phss,index));
  1289. */
  1290. while ((phss > 0) && (size < in_buf_len)) {
  1291. bit = ((*phsm << i) & SUPPRESS);
  1292. if (bit == SUPPRESS) {
  1293. *out_buf = *phsf;
  1294. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE,
  1295. DBG_LVL_ALL,
  1296. "\nDECOMP:In phss %d phsf %d output %d",
  1297. phss, *phsf, *out_buf);
  1298. } else {
  1299. *out_buf = *in_buf;
  1300. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_RECEIVE,
  1301. DBG_LVL_ALL,
  1302. "\nDECOMP:In phss %d input %d output %d",
  1303. phss, *in_buf, *out_buf);
  1304. in_buf++;
  1305. size++;
  1306. }
  1307. out_buf++;
  1308. phsf++;
  1309. phss--;
  1310. i++;
  1311. *header_size = *header_size + 1;
  1312. if (i > MAX_NO_BIT) {
  1313. i = 0;
  1314. phsm++;
  1315. }
  1316. }
  1317. return size;
  1318. }
  1319. /*
  1320. * Procedure: phs_compress
  1321. *
  1322. * Description: This routine suppresses the static fields within the packet.
  1323. * Before that it will verify the fields to be suppressed with the corresponding
  1324. * fields in the phsf. For verification it checks the phsv field of PHS rule.
  1325. * If set and verification succeeds it suppresses the field.If any one static
  1326. * field is found different none of the static fields are suppressed then the
  1327. * packet is sent as uncompressed packet with phsi=0.
  1328. *
  1329. * Arguments:
  1330. * phs_rule - ptr to PHS rule.
  1331. * in_buf - ptr to incoming packet buffer.
  1332. * out_buf - ptr to output buffer where the suppressed header is
  1333. * copied.
  1334. * header_size - ptr to field which holds the phss.
  1335. *
  1336. * Returns:
  1337. * size - The number of bytes copied into the output buffer i.e
  1338. * dynamic fields
  1339. * 0 - If PHS rule is NULL.If PHSV field is not set. If the
  1340. * verification fails.
  1341. */
  1342. static int phs_compress(struct bcm_phs_rule *phs_rule,
  1343. unsigned char *in_buf,
  1344. unsigned char *out_buf,
  1345. UINT *header_size,
  1346. UINT *new_header_size)
  1347. {
  1348. unsigned char *old_addr = out_buf;
  1349. int suppress = 0;
  1350. struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
  1351. if (phs_rule == NULL) {
  1352. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
  1353. "\nphs_compress(): phs_rule null!");
  1354. *out_buf = ZERO_PHSI;
  1355. return STATUS_PHS_NOCOMPRESSION;
  1356. }
  1357. if (phs_rule->u8PHSS <= *new_header_size)
  1358. *header_size = phs_rule->u8PHSS;
  1359. else
  1360. *header_size = *new_header_size;
  1361. /* To copy PHSI */
  1362. out_buf++;
  1363. suppress = verify_suppress_phsf(in_buf, out_buf, phs_rule->u8PHSF,
  1364. phs_rule->u8PHSM, phs_rule->u8PHSS,
  1365. phs_rule->u8PHSV, new_header_size);
  1366. if (suppress == STATUS_PHS_COMPRESSED) {
  1367. *old_addr = (unsigned char)phs_rule->u8PHSI;
  1368. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
  1369. "\nCOMP:In phs_compress phsi %d",
  1370. phs_rule->u8PHSI);
  1371. } else {
  1372. *old_addr = ZERO_PHSI;
  1373. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
  1374. "\nCOMP:In phs_compress PHSV Verification failed");
  1375. }
  1376. return suppress;
  1377. }
  1378. /*
  1379. * Procedure: verify_suppress_phsf
  1380. *
  1381. * Description: This routine verifies the fields of the packet and if all the
  1382. * static fields are equal it adds the phsi of that PHS rule.If any static
  1383. * field differs it woun't suppress any field.
  1384. *
  1385. * Arguments:
  1386. * rules_set - ptr to classifier_rules.
  1387. * in_buffer - ptr to incoming packet buffer.
  1388. * out_buffer - ptr to output buffer where the suppressed header is copied.
  1389. * phsf - ptr to phsf.
  1390. * phsm - ptr to phsm.
  1391. * phss - variable holding phss.
  1392. *
  1393. * Returns:
  1394. * size - The number of bytes copied into the output buffer i.e dynamic
  1395. * fields.
  1396. * 0 - Packet has failed the verification.
  1397. */
  1398. static int verify_suppress_phsf(unsigned char *in_buffer,
  1399. unsigned char *out_buffer,
  1400. unsigned char *phsf,
  1401. unsigned char *phsm,
  1402. unsigned int phss,
  1403. unsigned int phsv,
  1404. UINT *new_header_size)
  1405. {
  1406. unsigned int size = 0;
  1407. int bit, i = 0;
  1408. struct bcm_mini_adapter *Adapter = GET_BCM_ADAPTER(gblpnetdev);
  1409. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
  1410. "\nCOMP:In verify_phsf PHSM - 0x%X", *phsm);
  1411. if (phss > (*new_header_size))
  1412. phss = *new_header_size;
  1413. while (phss > 0) {
  1414. bit = ((*phsm << i) & SUPPRESS);
  1415. if (bit == SUPPRESS) {
  1416. if (*in_buffer != *phsf) {
  1417. if (phsv == VERIFY) {
  1418. BCM_DEBUG_PRINT(Adapter,
  1419. DBG_TYPE_OTHERS,
  1420. PHS_SEND,
  1421. DBG_LVL_ALL,
  1422. "\nCOMP:In verify_phsf failed for field %d buf %d phsf %d",
  1423. phss,
  1424. *in_buffer,
  1425. *phsf);
  1426. return STATUS_PHS_NOCOMPRESSION;
  1427. }
  1428. } else
  1429. BCM_DEBUG_PRINT(Adapter,
  1430. DBG_TYPE_OTHERS,
  1431. PHS_SEND,
  1432. DBG_LVL_ALL,
  1433. "\nCOMP:In verify_phsf success for field %d buf %d phsf %d",
  1434. phss,
  1435. *in_buffer,
  1436. *phsf);
  1437. } else {
  1438. *out_buffer = *in_buffer;
  1439. BCM_DEBUG_PRINT(Adapter,
  1440. DBG_TYPE_OTHERS,
  1441. PHS_SEND,
  1442. DBG_LVL_ALL,
  1443. "\nCOMP:In copying_header input %d out %d",
  1444. *in_buffer,
  1445. *out_buffer);
  1446. out_buffer++;
  1447. size++;
  1448. }
  1449. in_buffer++;
  1450. phsf++;
  1451. phss--;
  1452. i++;
  1453. if (i > MAX_NO_BIT) {
  1454. i = 0;
  1455. phsm++;
  1456. }
  1457. }
  1458. BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,
  1459. "\nCOMP:In verify_phsf success");
  1460. *new_header_size = size;
  1461. return STATUS_PHS_COMPRESSED;
  1462. }