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

Generated by: LCOV version 1.14