ipa_ipv6ct.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911
  1. /*
  2. * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions are
  6. * met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above
  10. * copyright notice, this list of conditions and the following
  11. * disclaimer in the documentation and/or other materials provided
  12. * with the distribution.
  13. * * Neither the name of The Linux Foundation nor the names of its
  14. * contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
  18. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  19. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
  20. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
  21. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  22. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  23. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  24. * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  25. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  26. * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
  27. * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. */
  29. #include "ipa_ipv6ct.h"
  30. #include "ipa_ipv6cti.h"
  31. #include <sys/ioctl.h>
  32. #include <stdlib.h>
  33. #include <errno.h>
  34. #include <pthread.h>
  35. #include <unistd.h>
  36. #define IPA_IPV6CT_DEBUG_FILE_PATH "/sys/kernel/debug/ipa/ipv6ct"
  37. #define IPA_UC_ACT_DEBUG_FILE_PATH "/sys/kernel/debug/ipa/uc_act_table"
  38. #define IPA_IPV6CT_TABLE_NAME "IPA IPv6CT table"
  39. static int ipa_ipv6ct_create_table(ipa_ipv6ct_table* ipv6ct_table, uint16_t number_of_entries, uint8_t table_index);
  40. static int ipa_ipv6ct_destroy_table(ipa_ipv6ct_table* ipv6ct_table);
  41. static void ipa_ipv6ct_create_table_dma_cmd_helpers(ipa_ipv6ct_table* ipv6ct_table, uint8_t table_indx);
  42. static int ipa_ipv6ct_post_init_cmd(ipa_ipv6ct_table* ipv6ct_table, uint8_t tbl_index);
  43. static int ipa_ipv6ct_post_dma_cmd(struct ipa_ioc_nat_dma_cmd* cmd);
  44. static uint16_t ipa_ipv6ct_hash(const ipa_ipv6ct_rule* rule, uint16_t size);
  45. static uint16_t ipa_ipv6ct_xor_segments(uint64_t num);
  46. static int table_entry_is_valid(void* entry);
  47. static uint16_t table_entry_get_next_index(void* entry);
  48. static uint16_t table_entry_get_prev_index(void* entry, uint16_t entry_index, void* meta, uint16_t base_table_size);
  49. static void table_entry_set_prev_index(void* entry, uint16_t entry_index, uint16_t prev_index,
  50. void* meta, uint16_t base_table_size);
  51. static int table_entry_head_insert(void* entry, void* user_data, uint16_t* dma_command_data);
  52. static int table_entry_tail_insert(void* entry, void* user_data);
  53. static uint16_t table_entry_get_delete_head_dma_command_data(void* head, void* next_entry);
  54. static ipa_ipv6ct ipv6ct;
  55. static pthread_mutex_t ipv6ct_mutex = PTHREAD_MUTEX_INITIALIZER;
  56. static ipa_table_entry_interface entry_interface =
  57. {
  58. table_entry_is_valid,
  59. table_entry_get_next_index,
  60. table_entry_get_prev_index,
  61. table_entry_set_prev_index,
  62. table_entry_head_insert,
  63. table_entry_tail_insert,
  64. table_entry_get_delete_head_dma_command_data
  65. };
  66. /**
  67. * ipa_ipv6ct_add_tbl() - Adds a new IPv6CT table
  68. * @number_of_entries: [in] number of IPv6CT entries
  69. * @table_handle: [out] handle of new IPv6CT table
  70. *
  71. * This function creates new IPv6CT table and posts IPv6CT init command to HW
  72. *
  73. * Returns: 0 On Success, negative on failure
  74. */
  75. int ipa_ipv6ct_add_tbl(uint16_t number_of_entries, uint32_t* table_handle)
  76. {
  77. int ret;
  78. ipa_ipv6ct_table* ipv6ct_table;
  79. IPADBG("\n");
  80. if (table_handle == NULL || number_of_entries == 0)
  81. {
  82. IPAERR("Invalid parameters table_handle=%pK number_of_entries=%d\n", table_handle, number_of_entries);
  83. return -EINVAL;
  84. }
  85. *table_handle = 0;
  86. if (ipv6ct.table_cnt >= IPA_IPV6CT_MAX_TBLS)
  87. {
  88. IPAERR("Can't add addition IPv6 connection tracking table. Maximum %d tables allowed\n", IPA_IPV6CT_MAX_TBLS);
  89. return -EINVAL;
  90. }
  91. if (!ipv6ct.ipa_desc)
  92. {
  93. ipv6ct.ipa_desc = ipa_descriptor_open();
  94. if (ipv6ct.ipa_desc == NULL)
  95. {
  96. IPAERR("failed to open IPA driver file descriptor\n");
  97. return -EIO;
  98. }
  99. }
  100. if (ipv6ct.ipa_desc->ver < IPA_HW_v4_0)
  101. {
  102. IPAERR("IPv6 connection tracking isn't supported for IPA version %d\n", ipv6ct.ipa_desc->ver);
  103. ret = -EPERM;
  104. goto bail_ipa_desc;
  105. }
  106. ipv6ct_table = &ipv6ct.tables[ipv6ct.table_cnt];
  107. ret = ipa_ipv6ct_create_table(ipv6ct_table, number_of_entries, ipv6ct.table_cnt);
  108. if (ret)
  109. {
  110. IPAERR("unable to create ipv6ct table Error: %d\n", ret);
  111. goto bail_ipa_desc;
  112. }
  113. /* Initialize the ipa hw with ipv6ct table dimensions */
  114. ret = ipa_ipv6ct_post_init_cmd(ipv6ct_table, ipv6ct.table_cnt);
  115. if (ret)
  116. {
  117. IPAERR("unable to post ipv6ct_init command Error %d\n", ret);
  118. goto bail_ipv6ct_table;
  119. }
  120. /* Return table handle */
  121. ++ipv6ct.table_cnt;
  122. *table_handle = ipv6ct.table_cnt;
  123. IPADBG("Returning table handle 0x%x\n", *table_handle);
  124. return 0;
  125. bail_ipv6ct_table:
  126. ipa_ipv6ct_destroy_table(ipv6ct_table);
  127. bail_ipa_desc:
  128. if (!ipv6ct.table_cnt) {
  129. ipa_descriptor_close(ipv6ct.ipa_desc);
  130. ipv6ct.ipa_desc = NULL;
  131. }
  132. return ret;
  133. }
  134. int ipa_ipv6ct_del_tbl(uint32_t table_handle)
  135. {
  136. ipa_ipv6ct_table* ipv6ct_table;
  137. int ret;
  138. IPADBG("\n");
  139. if (ipv6ct.ipa_desc->ver < IPA_HW_v4_0)
  140. {
  141. IPAERR("IPv6 connection tracking isn't supported for IPA version %d\n", ipv6ct.ipa_desc->ver);
  142. return -EINVAL;
  143. }
  144. if (table_handle == IPA_TABLE_INVALID_ENTRY || table_handle > IPA_IPV6CT_MAX_TBLS)
  145. {
  146. IPAERR("invalid table handle %d passed\n", table_handle);
  147. return -EINVAL;
  148. }
  149. IPADBG("Passed Table Handle: 0x%x\n", table_handle);
  150. if (pthread_mutex_lock(&ipv6ct_mutex))
  151. {
  152. IPAERR("unable to lock the ipv6ct mutex\n");
  153. return -EINVAL;
  154. }
  155. ipv6ct_table = &ipv6ct.tables[table_handle - 1];
  156. if (!ipv6ct_table->mem_desc.valid)
  157. {
  158. IPAERR("invalid table handle %d\n", table_handle);
  159. ret = -EINVAL;
  160. goto unlock;
  161. }
  162. ret = ipa_ipv6ct_destroy_table(ipv6ct_table);
  163. if (ret)
  164. {
  165. IPAERR("unable to delete IPV6CT table with handle %d\n", table_handle);
  166. goto unlock;
  167. }
  168. if (!--ipv6ct.table_cnt) {
  169. ipa_descriptor_close(ipv6ct.ipa_desc);
  170. ipv6ct.ipa_desc = NULL;
  171. }
  172. unlock:
  173. if (pthread_mutex_unlock(&ipv6ct_mutex))
  174. {
  175. IPAERR("unable to unlock the ipv6ct mutex\n");
  176. return (ret) ? ret : -EPERM;
  177. }
  178. IPADBG("return\n");
  179. return ret;
  180. }
  181. int ipa_ipv6ct_add_rule(uint32_t table_handle, const ipa_ipv6ct_rule* user_rule, uint32_t* rule_handle)
  182. {
  183. int ret;
  184. ipa_ipv6ct_table* ipv6ct_table;
  185. uint16_t new_entry_index;
  186. uint32_t new_entry_handle;
  187. struct ipa_ioc_nat_dma_cmd* cmd;
  188. IPADBG("\n");
  189. if (ipv6ct.ipa_desc->ver < IPA_HW_v4_0)
  190. {
  191. IPAERR("IPv6 connection tracking isn't supported for IPA version %d\n", ipv6ct.ipa_desc->ver);
  192. return -EINVAL;
  193. }
  194. if (table_handle == IPA_TABLE_INVALID_ENTRY || table_handle > IPA_IPV6CT_MAX_TBLS ||
  195. rule_handle == NULL || user_rule == NULL)
  196. {
  197. IPAERR("Invalid parameters table_handle=%d rule_handle=%pK user_rule=%pK\n",
  198. table_handle, rule_handle, user_rule);
  199. return -EINVAL;
  200. }
  201. IPADBG("Passed Table handle: 0x%x\n", table_handle);
  202. if (user_rule->protocol == IPA_IPV6CT_INVALID_PROTO_FIELD_CMP)
  203. {
  204. IPAERR("invalid parameter protocol=%d\n", user_rule->protocol);
  205. return -EINVAL;
  206. }
  207. if (pthread_mutex_lock(&ipv6ct_mutex))
  208. {
  209. IPAERR("unable to lock the ipv6ct mutex\n");
  210. return -EINVAL;
  211. }
  212. ipv6ct_table = &ipv6ct.tables[table_handle - 1];
  213. if (!ipv6ct_table->mem_desc.valid)
  214. {
  215. IPAERR("invalid table handle %d\n", table_handle);
  216. ret = -EINVAL;
  217. goto unlock;
  218. }
  219. cmd = (struct ipa_ioc_nat_dma_cmd *)calloc(1,
  220. sizeof(struct ipa_ioc_nat_dma_cmd) +
  221. (MAX_DMA_ENTRIES_FOR_ADD * sizeof(struct ipa_ioc_nat_dma_one)));
  222. if (cmd == NULL)
  223. {
  224. IPAERR("unable to allocate memory for Talbe DMA command\n");
  225. ret = -ENOMEM;
  226. goto unlock;
  227. }
  228. cmd->entries = 0;
  229. new_entry_index = ipa_ipv6ct_hash(user_rule, ipv6ct_table->table.table_entries - 1);
  230. ret = ipa_table_add_entry(&ipv6ct_table->table, (void*)user_rule, &new_entry_index, &new_entry_handle, cmd);
  231. if (ret)
  232. {
  233. IPAERR("failed to add a new IPV6CT entry\n");
  234. goto fail_add_entry;
  235. }
  236. ret = ipa_ipv6ct_post_dma_cmd(cmd);
  237. if (ret)
  238. {
  239. IPAERR("unable to post dma command\n");
  240. goto bail;
  241. }
  242. free(cmd);
  243. if (pthread_mutex_unlock(&ipv6ct_mutex))
  244. {
  245. IPAERR("unable to unlock the ipv6ct mutex\n");
  246. return -EPERM;
  247. }
  248. *rule_handle = new_entry_handle;
  249. IPADBG("return\n");
  250. return 0;
  251. bail:
  252. ipa_table_erase_entry(&ipv6ct_table->table, new_entry_index);
  253. fail_add_entry:
  254. free(cmd);
  255. unlock:
  256. if (pthread_mutex_unlock(&ipv6ct_mutex))
  257. IPAERR("unable to unlock the ipv6ct mutex\n");
  258. return ret;
  259. }
  260. int ipa_ipv6ct_del_rule(uint32_t table_handle, uint32_t rule_handle)
  261. {
  262. ipa_ipv6ct_table* ipv6ct_table;
  263. struct ipa_ioc_nat_dma_cmd* cmd;
  264. ipa_table_iterator table_iterator;
  265. ipa_ipv6ct_hw_entry* entry;
  266. uint16_t index;
  267. int ret;
  268. IPADBG("\n");
  269. if (ipv6ct.ipa_desc->ver < IPA_HW_v4_0)
  270. {
  271. IPAERR("IPv6 connection tracking isn't supported for IPA version %d\n", ipv6ct.ipa_desc->ver);
  272. return -EINVAL;
  273. }
  274. if (table_handle == IPA_TABLE_INVALID_ENTRY || table_handle > IPA_IPV6CT_MAX_TBLS ||
  275. rule_handle == IPA_TABLE_INVALID_ENTRY)
  276. {
  277. IPAERR("Invalid parameters table_handle=%d rule_handle=%d\n", table_handle, rule_handle);
  278. return -EINVAL;
  279. }
  280. IPADBG("Passed Table: 0x%x and rule handle 0x%x\n", table_handle, rule_handle);
  281. if (pthread_mutex_lock(&ipv6ct_mutex))
  282. {
  283. IPAERR("unable to lock the ipv6ct mutex\n");
  284. return -EINVAL;
  285. }
  286. ipv6ct_table = &ipv6ct.tables[table_handle - 1];
  287. if (!ipv6ct_table->mem_desc.valid)
  288. {
  289. IPAERR("invalid table handle %d\n", table_handle);
  290. ret = -EINVAL;
  291. goto unlock;
  292. }
  293. ret = ipa_table_get_entry(&ipv6ct_table->table, rule_handle, (void**)&entry, &index);
  294. if (ret)
  295. {
  296. IPAERR("unable to retrive the entry with handle=%d in IPV6CT table with handle=%d\n",
  297. rule_handle, table_handle);
  298. goto unlock;
  299. }
  300. ret = ipa_table_iterator_init(&table_iterator, &ipv6ct_table->table, entry, index);
  301. if (ret)
  302. {
  303. IPAERR("unable to create iterator which points to the entry index=%d in IPV6CT table with handle=%d\n",
  304. index, table_handle);
  305. goto unlock;
  306. }
  307. cmd = (struct ipa_ioc_nat_dma_cmd *)calloc(1,
  308. sizeof(struct ipa_ioc_nat_dma_cmd) +
  309. (MAX_DMA_ENTRIES_FOR_DEL * sizeof(struct ipa_ioc_nat_dma_one)));
  310. if (cmd == NULL)
  311. {
  312. IPAERR("unable to allocate memory for Talbe DMA command\n");
  313. ret = -ENOMEM;
  314. goto unlock;
  315. }
  316. cmd->entries = 0;
  317. ipa_table_create_delete_command(&ipv6ct_table->table, cmd, &table_iterator);
  318. ret = ipa_ipv6ct_post_dma_cmd(cmd);
  319. if (ret)
  320. {
  321. IPAERR("unable to post dma command\n");
  322. goto fail;
  323. }
  324. if (!ipa_table_iterator_is_head_with_tail(&table_iterator))
  325. {
  326. /* The entry can be deleted */
  327. uint8_t is_prev_empty = (table_iterator.prev_entry != NULL &&
  328. ((ipa_ipv6ct_hw_entry*)table_iterator.prev_entry)->protocol == IPA_IPV6CT_INVALID_PROTO_FIELD_CMP);
  329. ipa_table_delete_entry(&ipv6ct_table->table, &table_iterator, is_prev_empty);
  330. }
  331. fail:
  332. free(cmd);
  333. unlock:
  334. if (pthread_mutex_unlock(&ipv6ct_mutex))
  335. {
  336. IPAERR("unable to unlock the ipv6ct mutex\n");
  337. return (ret) ? ret : -EPERM;
  338. }
  339. IPADBG("return\n");
  340. return ret;
  341. }
  342. int ipa_ipv6ct_query_timestamp(uint32_t table_handle, uint32_t rule_handle, uint32_t* time_stamp)
  343. {
  344. int ret;
  345. ipa_ipv6ct_table* ipv6ct_table;
  346. ipa_ipv6ct_hw_entry *entry;
  347. IPADBG("\n");
  348. if (ipv6ct.ipa_desc->ver < IPA_HW_v4_0)
  349. {
  350. IPAERR("IPv6 connection tracking isn't supported for IPA version %d\n", ipv6ct.ipa_desc->ver);
  351. return -EINVAL;
  352. }
  353. if (table_handle == IPA_TABLE_INVALID_ENTRY || table_handle > IPA_IPV6CT_MAX_TBLS ||
  354. rule_handle == IPA_TABLE_INVALID_ENTRY || time_stamp == NULL)
  355. {
  356. IPAERR("invalid parameters passed table_handle=%d rule_handle=%d time_stamp=%pK\n",
  357. table_handle, rule_handle, time_stamp);
  358. return -EINVAL;
  359. }
  360. IPADBG("Passed Table: %d and rule handle %d\n", table_handle, rule_handle);
  361. if (pthread_mutex_lock(&ipv6ct_mutex))
  362. {
  363. IPAERR("unable to lock the ipv6ct mutex\n");
  364. return -EINVAL;
  365. }
  366. ipv6ct_table = &ipv6ct.tables[table_handle - 1];
  367. if (!ipv6ct_table->mem_desc.valid)
  368. {
  369. IPAERR("invalid table handle %d\n", table_handle);
  370. ret = -EINVAL;
  371. goto unlock;
  372. }
  373. ret = ipa_table_get_entry(&ipv6ct_table->table, rule_handle, (void**)&entry, NULL);
  374. if (ret)
  375. {
  376. IPAERR("unable to retrive the entry with handle=%d in IPV6CT table with handle=%d\n",
  377. rule_handle, table_handle);
  378. goto unlock;
  379. }
  380. *time_stamp = entry->time_stamp;
  381. unlock:
  382. if (pthread_mutex_unlock(&ipv6ct_mutex))
  383. {
  384. IPAERR("unable to unlock the ipv6ct mutex\n");
  385. return (ret) ? ret : -EPERM;
  386. }
  387. IPADBG("return\n");
  388. return ret;
  389. }
  390. /**
  391. * ipv6ct_hash() - Find the index into ipv6ct table
  392. * @rule: [in] an IPv6CT rule
  393. * @size: [in] size of the IPv6CT table
  394. *
  395. * This hash method is used to find the hash index of an entry into IPv6CT table.
  396. * In case of result zero, N-1 will be returned, where N is size of IPv6CT table.
  397. *
  398. * Returns: >0 index into IPv6CT table, negative on failure
  399. */
  400. static uint16_t ipa_ipv6ct_hash(const ipa_ipv6ct_rule* rule, uint16_t size)
  401. {
  402. uint16_t hash = 0;
  403. IPADBG("src_ipv6_lsb 0x%llx\n", rule->src_ipv6_lsb);
  404. IPADBG("src_ipv6_msb 0x%llx\n", rule->src_ipv6_msb);
  405. IPADBG("dest_ipv6_lsb 0x%llx\n", rule->dest_ipv6_lsb);
  406. IPADBG("dest_ipv6_msb 0x%llx\n", rule->dest_ipv6_msb);
  407. IPADBG("src_port: 0x%x dest_port: 0x%x\n", rule->src_port, rule->dest_port);
  408. IPADBG("protocol: 0x%x size: 0x%x\n", rule->protocol, size);
  409. hash ^= ipa_ipv6ct_xor_segments(rule->src_ipv6_lsb);
  410. hash ^= ipa_ipv6ct_xor_segments(rule->src_ipv6_msb);
  411. hash ^= ipa_ipv6ct_xor_segments(rule->dest_ipv6_lsb);
  412. hash ^= ipa_ipv6ct_xor_segments(rule->dest_ipv6_msb);
  413. hash ^= rule->src_port;
  414. hash ^= rule->dest_port;
  415. hash ^= rule->protocol;
  416. /*
  417. * The size passed to hash function expected be power^2-1, while the actual size is power^2,
  418. * actual_size = size + 1
  419. */
  420. hash &= size;
  421. /* If the hash resulted to zero then set it to maximum value as zero is unused entry in ipv6ct table */
  422. if (hash == 0)
  423. {
  424. hash = size;
  425. }
  426. IPADBG("ipa_ipv6ct_hash returning value: %d\n", hash);
  427. return hash;
  428. }
  429. static uint16_t ipa_ipv6ct_xor_segments(uint64_t num)
  430. {
  431. const uint64_t mask = 0xffff;
  432. const size_t bits_in_two_byte = 16;
  433. uint16_t ret = 0;
  434. IPADBG("\n");
  435. while (num)
  436. {
  437. ret ^= (uint16_t)(num & mask);
  438. num >>= bits_in_two_byte;
  439. }
  440. IPADBG("return\n");
  441. return ret;
  442. }
  443. static int table_entry_is_valid(void* entry)
  444. {
  445. ipa_ipv6ct_hw_entry* ipv6ct_entry = (ipa_ipv6ct_hw_entry*)entry;
  446. IPADBG("\n");
  447. return ipv6ct_entry->enable;
  448. }
  449. static uint16_t table_entry_get_next_index(void* entry)
  450. {
  451. uint16_t result;
  452. ipa_ipv6ct_hw_entry* ipv6ct_entry = (ipa_ipv6ct_hw_entry*)entry;
  453. IPADBG("\n");
  454. result = ipv6ct_entry->next_index;
  455. IPADBG("Next entry of %pK is %d\n", entry, result);
  456. return result;
  457. }
  458. static uint16_t table_entry_get_prev_index(void* entry, uint16_t entry_index, void* meta, uint16_t base_table_size)
  459. {
  460. uint16_t result;
  461. ipa_ipv6ct_hw_entry* ipv6ct_entry = (ipa_ipv6ct_hw_entry*)entry;
  462. IPADBG("\n");
  463. result = ipv6ct_entry->prev_index;
  464. IPADBG("Previous entry of %d is %d\n", entry_index, result);
  465. return result;
  466. }
  467. static void table_entry_set_prev_index(void* entry, uint16_t entry_index, uint16_t prev_index,
  468. void* meta, uint16_t base_table_size)
  469. {
  470. ipa_ipv6ct_hw_entry* ipv6ct_entry = (ipa_ipv6ct_hw_entry*)entry;
  471. IPADBG("Previous entry of %d is %d\n", entry_index, prev_index);
  472. ipv6ct_entry->prev_index = prev_index;
  473. IPADBG("return\n");
  474. }
  475. static int table_entry_copy_from_user(void* entry, void* user_data)
  476. {
  477. ipa_ipv6ct_hw_entry* ipv6ct_entry = (ipa_ipv6ct_hw_entry*)entry;
  478. const ipa_ipv6ct_rule* user_rule = (const ipa_ipv6ct_rule*)user_data;
  479. IPADBG("\n");
  480. ipv6ct_entry->src_ipv6_lsb = user_rule->src_ipv6_lsb;
  481. ipv6ct_entry->src_ipv6_msb = user_rule->src_ipv6_msb;
  482. ipv6ct_entry->dest_ipv6_lsb = user_rule->dest_ipv6_lsb;
  483. ipv6ct_entry->dest_ipv6_msb = user_rule->dest_ipv6_msb;
  484. ipv6ct_entry->protocol = user_rule->protocol;
  485. ipv6ct_entry->src_port = user_rule->src_port;
  486. ipv6ct_entry->dest_port = user_rule->dest_port;
  487. ipv6ct_entry->ucp = user_rule->ucp;
  488. ipv6ct_entry->uc_activation_index = user_rule->uc_activation_index;
  489. ipv6ct_entry->s = user_rule->s;
  490. switch (user_rule->direction_settings)
  491. {
  492. case IPA_IPV6CT_DIRECTION_DENY_ALL:
  493. break;
  494. case IPA_IPV6CT_DIRECTION_ALLOW_OUT:
  495. ipv6ct_entry->out_allowed = IPA_IPV6CT_DIRECTION_ALLOW_BIT;
  496. break;
  497. case IPA_IPV6CT_DIRECTION_ALLOW_IN:
  498. ipv6ct_entry->in_allowed = IPA_IPV6CT_DIRECTION_ALLOW_BIT;
  499. break;
  500. case IPA_IPV6CT_DIRECTION_ALLOW_ALL:
  501. ipv6ct_entry->out_allowed = IPA_IPV6CT_DIRECTION_ALLOW_BIT;
  502. ipv6ct_entry->in_allowed = IPA_IPV6CT_DIRECTION_ALLOW_BIT;
  503. break;
  504. default:
  505. IPAERR("wrong value for IPv6CT direction setting parameter %d\n", user_rule->direction_settings);
  506. return -EINVAL;
  507. }
  508. IPADBG("return\n");
  509. return 0;
  510. }
  511. static int table_entry_head_insert(void* entry, void* user_data, uint16_t* dma_command_data)
  512. {
  513. int ret;
  514. IPADBG("\n");
  515. ret = table_entry_copy_from_user(entry, user_data);
  516. if (ret)
  517. {
  518. IPAERR("unable to copy from user a new entry\n");
  519. return ret;
  520. }
  521. *dma_command_data = 0;
  522. ((ipa_ipv6ct_flags*)dma_command_data)->enable = IPA_IPV6CT_FLAG_ENABLE_BIT;
  523. IPADBG("return\n");
  524. return 0;
  525. }
  526. static int table_entry_tail_insert(void* entry, void* user_data)
  527. {
  528. int ret;
  529. IPADBG("\n");
  530. ret = table_entry_copy_from_user(entry, user_data);
  531. if (ret)
  532. {
  533. IPAERR("unable to copy from user a new entry\n");
  534. return ret;
  535. }
  536. ((ipa_ipv6ct_hw_entry*)entry)->enable = IPA_IPV6CT_FLAG_ENABLE_BIT;
  537. IPADBG("return\n");
  538. return 0;
  539. }
  540. static uint16_t table_entry_get_delete_head_dma_command_data(void* head, void* next_entry)
  541. {
  542. IPADBG("\n");
  543. return IPA_IPV6CT_INVALID_PROTO_FIELD_VALUE;
  544. }
  545. /**
  546. * ipa_ipv6ct_create_table() - Creates a new IPv6CT table
  547. * @ipv6ct_table: [in] IPv6CT table
  548. * @number_of_entries: [in] number of IPv6CT entries
  549. * @table_index: [in] the index of the IPv6CT table
  550. *
  551. * This function creates new IPv6CT table:
  552. * - Initializes table, memory descriptor and table_dma_cmd_helpers structures
  553. * - Allocates, maps and clears the memory for table
  554. *
  555. * Returns: 0 On Success, negative on failure
  556. */
  557. static int ipa_ipv6ct_create_table(ipa_ipv6ct_table* ipv6ct_table, uint16_t number_of_entries, uint8_t table_index)
  558. {
  559. int ret, size;
  560. IPADBG("\n");
  561. ipa_table_init(
  562. &ipv6ct_table->table, IPA_IPV6CT_TABLE_NAME, IPA_NAT_MEM_IN_DDR,
  563. sizeof(ipa_ipv6ct_hw_entry), NULL, 0, &entry_interface);
  564. ret = ipa_table_calculate_entries_num(
  565. &ipv6ct_table->table, number_of_entries, IPA_NAT_MEM_IN_DDR);
  566. if (ret)
  567. {
  568. IPAERR("unable to calculate number of entries in ipv6ct table %d, while required by user %d\n",
  569. table_index, number_of_entries);
  570. return ret;
  571. }
  572. size = ipa_table_calculate_size(&ipv6ct_table->table);
  573. IPADBG("IPv6CT table size: %d\n", size);
  574. ipa_mem_descriptor_init(
  575. &ipv6ct_table->mem_desc,
  576. IPA_IPV6CT_DEV_NAME,
  577. size,
  578. table_index,
  579. IPA_IOC_ALLOC_IPV6CT_TABLE,
  580. IPA_IOC_DEL_IPV6CT_TABLE,
  581. false); /* false here means don't consider using sram */
  582. ret = ipa_mem_descriptor_allocate_memory(
  583. &ipv6ct_table->mem_desc,
  584. ipv6ct.ipa_desc->fd);
  585. if (ret)
  586. {
  587. IPAERR("unable to allocate ipv6ct memory descriptor Error: %d\n", ret);
  588. goto bail;
  589. }
  590. ipa_table_calculate_addresses(&ipv6ct_table->table, ipv6ct_table->mem_desc.base_addr);
  591. ipa_table_reset(&ipv6ct_table->table);
  592. ipa_ipv6ct_create_table_dma_cmd_helpers(ipv6ct_table, table_index);
  593. IPADBG("return\n");
  594. return 0;
  595. bail:
  596. memset(ipv6ct_table, 0, sizeof(*ipv6ct_table));
  597. return ret;
  598. }
  599. static int ipa_ipv6ct_destroy_table(ipa_ipv6ct_table* ipv6ct_table)
  600. {
  601. int ret;
  602. IPADBG("\n");
  603. ret = ipa_mem_descriptor_delete(&ipv6ct_table->mem_desc, ipv6ct.ipa_desc->fd);
  604. if (ret)
  605. IPAERR("unable to delete IPV6CT descriptor\n");
  606. memset(ipv6ct_table, 0, sizeof(*ipv6ct_table));
  607. IPADBG("return\n");
  608. return ret;
  609. }
  610. /**
  611. * ipa_ipv6ct_create_table_dma_cmd_helpers() -
  612. * Creates dma_cmd_helpers for base table in the received IPv6CT table
  613. * @ipv6ct_table: [in] IPv6CT table
  614. * @table_indx: [in] The index of the IPv6CT table
  615. *
  616. * A DMA command helper helps to generate the DMA command for one
  617. * specific field change. Each table has 3 different types of field
  618. * change: update_head, update_entry and delete_head. This function
  619. * creates the helpers and updates the base table correspondingly.
  620. */
  621. static void ipa_ipv6ct_create_table_dma_cmd_helpers(
  622. ipa_ipv6ct_table* ipv6ct_table,
  623. uint8_t table_indx )
  624. {
  625. IPADBG("\n");
  626. ipa_table_dma_cmd_helper_init(
  627. &ipv6ct_table->table_dma_cmd_helpers[IPA_IPV6CT_TABLE_FLAGS],
  628. table_indx,
  629. IPA_IPV6CT_BASE_TBL,
  630. IPA_IPV6CT_EXPN_TBL,
  631. ipv6ct_table->mem_desc.addr_offset + IPA_IPV6CT_RULE_FLAG_FIELD_OFFSET);
  632. ipa_table_dma_cmd_helper_init(
  633. &ipv6ct_table->table_dma_cmd_helpers[IPA_IPV6CT_TABLE_NEXT_INDEX],
  634. table_indx,
  635. IPA_IPV6CT_BASE_TBL,
  636. IPA_IPV6CT_EXPN_TBL,
  637. ipv6ct_table->mem_desc.addr_offset + IPA_IPV6CT_RULE_NEXT_FIELD_OFFSET);
  638. ipa_table_dma_cmd_helper_init(
  639. &ipv6ct_table->table_dma_cmd_helpers[IPA_IPV6CT_TABLE_PROTOCOL],
  640. table_indx,
  641. IPA_IPV6CT_BASE_TBL,
  642. IPA_IPV6CT_EXPN_TBL,
  643. ipv6ct_table->mem_desc.addr_offset + IPA_IPV6CT_RULE_PROTO_FIELD_OFFSET);
  644. ipv6ct_table->table.dma_help[HELP_UPDATE_HEAD] =
  645. &ipv6ct_table->table_dma_cmd_helpers[IPA_IPV6CT_TABLE_FLAGS];
  646. ipv6ct_table->table.dma_help[HELP_UPDATE_ENTRY] =
  647. &ipv6ct_table->table_dma_cmd_helpers[IPA_IPV6CT_TABLE_NEXT_INDEX];
  648. ipv6ct_table->table.dma_help[HELP_DELETE_HEAD] =
  649. &ipv6ct_table->table_dma_cmd_helpers[IPA_IPV6CT_TABLE_PROTOCOL];
  650. IPADBG("return\n");
  651. }
  652. static int ipa_ipv6ct_post_init_cmd(ipa_ipv6ct_table* ipv6ct_table, uint8_t tbl_index)
  653. {
  654. struct ipa_ioc_ipv6ct_init cmd;
  655. int ret;
  656. IPADBG("\n");
  657. cmd.tbl_index = tbl_index;
  658. cmd.base_table_offset = ipv6ct_table->mem_desc.addr_offset;
  659. cmd.expn_table_offset = cmd.base_table_offset + (ipv6ct_table->table.table_entries * sizeof(ipa_ipv6ct_hw_entry));
  660. /* Driverr/HW expected base table size to be power^2-1 due to H/W hash calculation */
  661. cmd.table_entries = ipv6ct_table->table.table_entries - 1;
  662. cmd.expn_table_entries = ipv6ct_table->table.expn_table_entries;
  663. ret = ioctl(ipv6ct.ipa_desc->fd, IPA_IOC_INIT_IPV6CT_TABLE, &cmd);
  664. if (ret)
  665. {
  666. IPAERR("unable to post init cmd Error: %d IPA fd %d\n", ret, ipv6ct.ipa_desc->fd);
  667. return ret;
  668. }
  669. IPADBG("Posted IPA_IOC_INIT_IPV6CT_TABLE to kernel successfully\n");
  670. return 0;
  671. }
  672. static int ipa_ipv6ct_post_dma_cmd(struct ipa_ioc_nat_dma_cmd* cmd)
  673. {
  674. IPADBG("\n");
  675. cmd->mem_type = IPA_NAT_MEM_IN_DDR;
  676. if (ioctl(ipv6ct.ipa_desc->fd, IPA_IOC_TABLE_DMA_CMD, cmd))
  677. {
  678. IPAERR("ioctl (IPA_IOC_TABLE_DMA_CMD) on fd %d has failed\n",
  679. ipv6ct.ipa_desc->fd);
  680. return -EIO;
  681. }
  682. IPADBG("posted IPA_IOC_TABLE_DMA_CMD to kernel successfully\n");
  683. return 0;
  684. }
  685. void ipa_ipv6ct_dump_table(uint32_t table_handle)
  686. {
  687. ipa_ipv6ct_table* ipv6ct_table;
  688. if (ipv6ct.ipa_desc->ver < IPA_HW_v4_0)
  689. {
  690. IPAERR("IPv6 connection tracking isn't supported for IPA version %d\n", ipv6ct.ipa_desc->ver);
  691. return;
  692. }
  693. if (table_handle == IPA_TABLE_INVALID_ENTRY || table_handle > IPA_IPV6CT_MAX_TBLS)
  694. {
  695. IPAERR("invalid parameters passed %d\n", table_handle);
  696. return;
  697. }
  698. if (pthread_mutex_lock(&ipv6ct_mutex))
  699. {
  700. IPAERR("unable to lock the ipv6ct mutex\n");
  701. return;
  702. }
  703. ipv6ct_table = &ipv6ct.tables[table_handle - 1];
  704. if (!ipv6ct_table->mem_desc.valid)
  705. {
  706. IPAERR("invalid table handle %d\n", table_handle);
  707. goto unlock;
  708. }
  709. /* Prevents interleaving with later kernel printouts. Flush doesn't help. */
  710. sleep(1);
  711. ipa_read_debug_info(IPA_IPV6CT_DEBUG_FILE_PATH);
  712. ipa_read_debug_info(IPA_UC_ACT_DEBUG_FILE_PATH);
  713. sleep(1);
  714. unlock:
  715. if (pthread_mutex_unlock(&ipv6ct_mutex))
  716. IPAERR("unable to unlock the ipv6ct mutex\n");
  717. }
  718. /**
  719. * ipa_ipv6ct_add_uc_act_entry() - add uc activation entry
  720. * @u: [in] structure specifying the uC activation entry
  721. *
  722. * Returns: 0 On Success, negative on failure
  723. */
  724. int ipa_ipv6ct_add_uc_act_entry(union ipa_ioc_uc_activation_entry *u)
  725. {
  726. IPADBG("\n");
  727. if(ioctl(ipv6ct.ipa_desc->fd, IPA_IOC_ADD_UC_ACT_ENTRY, u))
  728. {
  729. IPAERR("ioctl (IPA_IOC_ADD_UC_ACT_ENTRY) on fd %d has failed\n",
  730. ipv6ct.ipa_desc->fd);
  731. return -EIO;
  732. }
  733. IPADBG("posted IPA_IOC_ADD_UC_ACT_ENTRY to kernel successfully, index %d\n",
  734. u->ipv6_nat.index);
  735. return 0;
  736. }
  737. /**
  738. * ipa_ipv6ct_del_uc_act_entry() - del uc activation entry
  739. * @index: [in] index of the uc activation entry to be removed
  740. *
  741. * Returns: 0 On Success, negative on failure
  742. */
  743. int ipa_ipv6ct_del_uc_act_entry(uint16_t index)
  744. {
  745. IPADBG("\n");
  746. if(ioctl(ipv6ct.ipa_desc->fd, IPA_IOC_DEL_UC_ACT_ENTRY, index))
  747. {
  748. IPAERR("ioctl (IPA_IOC_DEL_UC_ACT_ENTRY) on fd %d has failed\n",
  749. ipv6ct.ipa_desc->fd);
  750. return -EIO;
  751. }
  752. IPADBG("posted IPA_IOC_DEL_UC_ACT_ENTRY to kernel successfully, index %d\n",
  753. index);
  754. return 0;
  755. }