LCOV - code coverage report
Current view: top level - root/contrail/vrouter/dpdk - vr_dpdk_table_mem.c (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 52 141 36.9 %
Date: 2026-08-03 02:19:58 Functions: 3 4 75.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * vr_dpdk_flow_mem.c -- memory allocation for flow table
       3             :  *
       4             :  * Copyright(c) 2014, Juniper Networks Inc.,
       5             :  * All rights reserved
       6             :  */
       7             : 
       8             : #include <stdint.h>
       9             : #include <sys/types.h>
      10             : #include <sys/mman.h>
      11             : #include <sys/stat.h>
      12             : #include <fcntl.h>
      13             : #include <unistd.h>
      14             : 
      15             : #include "vr_dpdk.h"
      16             : #include "vr_btable.h"
      17             : #include "vr_mem.h"
      18             : #include "nl_util.h"
      19             : 
      20             : #include <rte_errno.h>
      21             : 
      22             : #define MAX_LINE_SIZE   256
      23             : #define HPI_MAX         16
      24             : #define MOUNT_TABLE     "/proc/mounts"
      25             : 
      26             : struct vr_hugepage_info {
      27             :     char *mnt;
      28             :     size_t page_size;
      29             :     size_t size;
      30             :     uint32_t num_pages;
      31             : } vr_hugepage_md[HPI_MAX];
      32             : 
      33             : extern void *vr_flow_table, *vr_oflow_table;
      34             : extern void *vr_bridge_table, *vr_obridge_table;
      35             : extern unsigned char *vr_flow_path, *vr_bridge_table_path;
      36             : char flow_mem_file[VR_UNIX_PATH_MAX];
      37             : char bridge_mem_file[VR_UNIX_PATH_MAX];
      38             : 
      39             : static int
      40           0 : vr_hugepage_info_init(void)
      41             : {
      42           0 :     unsigned int i = 0, multiple = 1;
      43             :     char *str, *token;
      44             : 
      45             :     char *dev, *mnt, *fs, *options, *size;
      46             :     char *size_attr, *sys_hp_file;
      47           0 :     FILE *fp = NULL, *sys_fp = NULL;
      48             :     struct vr_hugepage_info *hp;
      49             : 
      50             :     char line[MAX_LINE_SIZE];
      51             :     char nr_pages[MAX_LINE_SIZE];
      52             : 
      53             : 
      54           0 :     fp = fopen(MOUNT_TABLE, "r");
      55           0 :     if (!fp)
      56           0 :         return -errno;
      57             : 
      58           0 :     while (fgets(line, MAX_LINE_SIZE, fp)) {
      59           0 :         if (i >= HPI_MAX)
      60           0 :             break;
      61             : 
      62           0 :         if ((str = strstr(line, "hugetlbfs"))) {
      63           0 :             hp = &vr_hugepage_md[i++];
      64           0 :             dev = strtok(line, " ");
      65           0 :             mnt = strtok(NULL, " ");
      66           0 :             fs = strtok(NULL, " ");
      67           0 :             options = strtok(NULL, " ");
      68             : 
      69             :             RTE_SET_USED(fs);
      70             :             RTE_SET_USED(dev);
      71             :             RTE_SET_USED(token);
      72             : 
      73           0 :             hp->mnt = malloc(strlen(mnt) + 1);
      74           0 :             memcpy(hp->mnt, mnt, strlen(mnt) + 1);
      75             : 
      76           0 :             if (strstr(options, "pagesize=1G") || strstr(options, "pagesize=1024M")) {
      77           0 :                 hp->page_size = (1024 * 1024 * 1024);
      78           0 :                 sys_hp_file =
      79             :                     "/sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages";
      80             :             } else {
      81           0 :                 hp->page_size = (2 * 1024 * 1024);
      82           0 :                 sys_hp_file =
      83             :                     "/sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages";
      84             :             }
      85             : 
      86           0 :             size = strstr(options, "size=");
      87           0 :             if (size && (size != options) && (*(size - 1) != ','))
      88           0 :                 size = strstr(size + 1, "size=");
      89             : 
      90           0 :             if (size && ((size == options) || (*(size - 1) == ','))) {
      91           0 :                 size += strlen("size=");
      92           0 :                 size = strtok(size, ",");
      93           0 :                 size_attr = size + strlen(size) - 1;
      94           0 :                 switch (*size_attr) {
      95           0 :                 case 'k':
      96             :                 case 'K':
      97           0 :                     multiple = 1024;
      98           0 :                     *size_attr = '\0';
      99           0 :                     break;
     100             : 
     101           0 :                 case 'M':
     102             :                 case 'm':
     103           0 :                     multiple = 1024 * 1024;
     104           0 :                     *size_attr = '\0';
     105           0 :                     break;
     106             : 
     107           0 :                 case 'G':
     108             :                 case 'g':
     109           0 :                     multiple = 1024 * 1024 * 1024;
     110           0 :                     *size_attr = '\0';
     111           0 :                     break;
     112             :                 }
     113             : 
     114           0 :                 hp->size = strtoul(size, NULL, 0) * multiple;
     115           0 :                 hp->num_pages = hp->size / hp->page_size;
     116             :             } else {
     117           0 :                 sys_fp = fopen(sys_hp_file, "r");
     118           0 :                 if (!sys_fp)
     119           0 :                     goto exit_func;
     120             : 
     121           0 :                 str = fgets(nr_pages, MAX_LINE_SIZE, sys_fp);
     122           0 :                 if (str == NULL)
     123           0 :                     goto exit_func;
     124           0 :                 hp->num_pages = strtoul(nr_pages, NULL, 0);
     125           0 :                 hp->size = hp->num_pages * hp->page_size;
     126             :             }
     127             : 
     128             :         }
     129             :     }
     130             : 
     131           0 : exit_func:
     132           0 :     if (fp)
     133           0 :         fclose(fp);
     134             : 
     135           0 :     if (sys_fp)
     136           0 :         fclose(sys_fp);
     137             : 
     138           0 :     return 0;
     139             : }
     140             : 
     141             : 
     142             : int
     143         106 : vr_dpdk_table_mem_init(unsigned int table, unsigned int entries,
     144             :         unsigned long size, unsigned int oentries, unsigned long osize)
     145             : {
     146             :     int ret, i, fd;
     147             : 
     148             :     void **table_p;
     149             :     char *shm_file;
     150         106 :     char *file_name, *touse_file_name = NULL;
     151             :     char *shmem_name, *hp_file_name;
     152             :     unsigned char **path;
     153             : 
     154             :     struct stat f_stat;
     155             :     struct vr_hugepage_info *hpi;
     156             : 
     157         106 :     if (!oentries) {
     158         106 :         oentries = (entries / 5 + 1023) & ~1023;
     159         106 :         osize = (size / entries) * oentries;
     160             :     }
     161             : 
     162         106 :     size += osize;
     163             : 
     164         106 :     switch (table) {
     165          53 :     case VR_MEM_FLOW_TABLE_OBJECT:
     166          53 :         shmem_name = "flow.shmem";
     167          53 :         hp_file_name = "flow";
     168          53 :         table_p = &vr_dpdk.flow_table;
     169          53 :         path = &vr_flow_path;
     170          53 :         vr_oflow_entries = oentries;
     171          53 :         shm_file = flow_mem_file;
     172          53 :         break;
     173             : 
     174          53 :     case VR_MEM_BRIDGE_TABLE_OBJECT:
     175          53 :         shmem_name = "bridge.shmem";
     176          53 :         hp_file_name = "bridge";
     177          53 :         table_p = &vr_dpdk.bridge_table;
     178          53 :         path = &vr_bridge_table_path;
     179          53 :         vr_bridge_oentries = oentries;
     180          53 :         shm_file = bridge_mem_file;
     181          53 :         break;
     182             : 
     183           0 :     default:
     184           0 :         return -EINVAL;
     185             :     }
     186             : 
     187         106 :     if (no_huge_set) {
     188             :         /* Create a shared memory under the socket directory. */
     189         106 :         ret = snprintf(shm_file, VR_UNIX_PATH_MAX, "%s/%s",
     190             :                 vr_socket_dir, shmem_name);
     191         106 :         if (ret >= VR_UNIX_PATH_MAX) {
     192           0 :             RTE_LOG(ERR, VROUTER, "Error creating shared memory file\n");
     193           0 :             return -ENOMEM;
     194             :         }
     195         106 :         touse_file_name = shm_file;
     196             :     } else {
     197           0 :         ret = vr_hugepage_info_init();
     198           0 :         if (ret < 0) {
     199           0 :             RTE_LOG(ERR, VROUTER, "Error initializing hugepage info: %s (%d)\n",
     200             :                 rte_strerror(-ret), -ret);
     201           0 :             return ret;
     202             :         }
     203             : 
     204           0 :         for (i = 0; i < HPI_MAX; i++) {
     205           0 :             hpi = &vr_hugepage_md[i];
     206           0 :             if (!hpi->mnt)
     207           0 :                 continue;
     208           0 :             file_name = malloc(strlen(hpi->mnt) + strlen(hp_file_name) + 2);
     209           0 :             sprintf(file_name, "%s/%s", hpi->mnt, hp_file_name);
     210           0 :             if (stat(file_name, &f_stat) == -1) {
     211           0 :                 if (!touse_file_name) {
     212           0 :                     if (hpi->size >= size) {
     213           0 :                         touse_file_name = file_name;
     214             :                     } else {
     215           0 :                         free(file_name);
     216             :                     }
     217             :                 }
     218             :             } else {
     219           0 :                 free(touse_file_name);
     220           0 :                 touse_file_name = file_name;
     221           0 :                 break;
     222             :             }
     223             :         }
     224             :     }
     225             : 
     226         106 :     if (touse_file_name) {
     227         106 :         fd = open(touse_file_name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
     228         106 :         if (fd == -1) {
     229           0 :             RTE_LOG(ERR, VROUTER, "Error opening file \"%s\": %s (%d)\n",
     230             :                 touse_file_name, rte_strerror(errno), errno);
     231           0 :             return -errno;
     232             :         }
     233             : 
     234         106 :         if (no_huge_set) {
     235         106 :             ret = ftruncate(fd, size);
     236         106 :             if (ret == -1) {
     237           0 :                 RTE_LOG(ERR, VROUTER, "Error truncating file %s: %s (%d)\n",
     238             :                     touse_file_name, rte_strerror(errno), errno);
     239           0 :                 return -errno;
     240             :             }
     241             :         }
     242             : 
     243         106 :         *table_p = mmap(NULL, size, PROT_READ | PROT_WRITE,
     244             :                 MAP_SHARED, fd, 0);
     245             :         /* the file descriptor is no longer needed */
     246         106 :         close(fd);
     247         106 :         if (*table_p == MAP_FAILED) {
     248           0 :             RTE_LOG(ERR, VROUTER, "Error mmapping file %s: %s (%d)\n",
     249             :                 touse_file_name, rte_strerror(errno), errno);
     250           0 :             return -errno;
     251             :         }
     252         106 :         memset(*table_p, 0, size);
     253         106 :         *path = (unsigned char *)touse_file_name;
     254             :     }
     255             : 
     256         106 :     return 0;
     257             : }
     258             : 
     259             : int
     260          53 : vr_dpdk_bridge_init(void)
     261             : {
     262          53 :     if (!vr_dpdk.bridge_table)
     263           0 :         return -1;
     264             : 
     265          53 :     vr_bridge_table = vr_dpdk.bridge_table;
     266          53 :     vr_obridge_table = vr_dpdk.bridge_table + VR_BRIDGE_TABLE_SIZE;
     267             : 
     268          53 :     return 0;
     269             : }
     270             : 
     271             : int
     272          53 : vr_dpdk_flow_init(void)
     273             : {
     274          53 :     if (!vr_dpdk.flow_table)
     275           0 :         return -1;
     276             : 
     277          53 :     vr_flow_table = vr_dpdk.flow_table;
     278          53 :     vr_oflow_table = vr_dpdk.flow_table + VR_FLOW_TABLE_SIZE;
     279             : 
     280          53 :     if (!vr_flow_table)
     281           0 :         return -1;
     282             : 
     283          53 :     vr_flow_hold_limit = VR_DPDK_MAX_FLOW_TABLE_HOLD_COUNT;
     284          53 :     RTE_LOG(INFO, VROUTER, "Max HOLD flow entries set to %u\n",
     285             :             vr_flow_hold_limit);
     286             : 
     287          53 :     return 0;
     288             : }

Generated by: LCOV version 1.14