LCOV - code coverage report
Current view: top level - root/contrail/vrouter/dp-core - vr_qos.c (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 35 502 7.0 %
Date: 2026-08-03 02:19:58 Functions: 4 26 15.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * vr_qos.c -- QOS implementation for vRouter datapath
       3             :  *
       4             :  * Copyright (c) 2015, Juniper Networks Inc.
       5             :  * All rights reserved
       6             :  */
       7             : #include <vr_os.h>
       8             : #include <vr_types.h>
       9             : #include <vr_packet.h>
      10             : 
      11             : #include "vr_message.h"
      12             : #include "vr_sandesh.h"
      13             : #include "vr_interface.h"
      14             : #include "vr_datapath.h"
      15             : #include "vr_qos.h"
      16             : #include "vr_offloads_dp.h"
      17             : 
      18             : unsigned int vr_qos_map_entries = VR_DEF_QOS_MAP_ENTRIES;
      19             : unsigned int vr_fc_map_entries = VR_DEF_FC_MAP_ENTRIES;
      20             : unsigned int vr_qos_map_entry_size = VR_QOS_MAP_ENTRY_SIZE;
      21             : 
      22             : static void
      23           0 : vr_qos_message_error(int error)
      24             : {
      25           0 :     vr_send_response(error);
      26           0 :     return;
      27             : }
      28             : 
      29             : unsigned int
      30           0 : vr_qos_map_req_get_size(void *object)
      31             : {
      32             :     unsigned int size;
      33           0 :     vr_qos_map_req *req = (vr_qos_map_req *)object;
      34             : 
      35           0 :     size = 4 * sizeof(*req);
      36           0 :     size += 4 * req->qmr_dscp_size;
      37           0 :     size += 4 * req->qmr_dscp_fc_id_size;
      38           0 :     size += 4 * req->qmr_mpls_qos_size;
      39           0 :     size += 4 * req->qmr_mpls_qos_fc_id_size;
      40           0 :     size += 4 * req->qmr_dotonep_size;
      41           0 :     size += 4 * req->qmr_dotonep_fc_id_size;
      42             : 
      43           0 :     return size;
      44             : }
      45             : 
      46             : static int
      47           0 : vr_qos_map_request_validate(vr_qos_map_req *req)
      48             : {
      49           0 :     if (req->qmr_id >= vr_qos_map_entries)
      50           0 :         return -EINVAL;
      51             : 
      52           0 :     if (req->qmr_dscp_size != req->qmr_dscp_fc_id_size)
      53           0 :         return -EINVAL;
      54             : 
      55           0 :     if (req->qmr_mpls_qos_size != req->qmr_mpls_qos_fc_id_size)
      56           0 :         return -EINVAL;
      57             : 
      58           0 :     if (req->qmr_dotonep_size != req->qmr_dotonep_fc_id_size)
      59           0 :         return -EINVAL;
      60             : 
      61           0 :     return 0;
      62             : }
      63             : 
      64             : static struct vr_forwarding_class *
      65          79 : vr_qos_map_get_fc(struct vrouter *router, unsigned int id)
      66             : {
      67          79 :     if (id >= vr_qos_map_entries)
      68           0 :         return NULL;
      69             : 
      70          79 :     return router->vr_qos_map[id];
      71             : }
      72             : 
      73             : static int
      74           0 : vr_qos_map_set_fc(struct vrouter *router, unsigned int id,
      75             :         struct vr_forwarding_class *fc_p)
      76             : {
      77           0 :     if (id >= vr_qos_map_entries)
      78           0 :         return -EINVAL;
      79             : 
      80           0 :     router->vr_qos_map[id] = fc_p;
      81           0 :     return 0;
      82             : }
      83             : 
      84             : static void
      85           0 : vr_qos_map_req_destroy(vr_qos_map_req *req)
      86             : {
      87           0 :     if (!req)
      88           0 :         return;
      89             : 
      90           0 :     if (req->qmr_dscp && req->qmr_dscp_size) {
      91           0 :         vr_free(req->qmr_dscp, VR_QOS_MAP_OBJECT);
      92           0 :         req->qmr_dscp = NULL;
      93           0 :         req->qmr_dscp_size = 0;
      94           0 :         if (req->qmr_dscp_fc_id) {
      95           0 :             vr_free(req->qmr_dscp_fc_id, VR_QOS_MAP_OBJECT);
      96           0 :             req->qmr_dscp_fc_id_size = 0;
      97             :         }
      98             :     }
      99             : 
     100           0 :     if (req->qmr_mpls_qos && req->qmr_mpls_qos_size) {
     101           0 :         vr_free(req->qmr_mpls_qos, VR_QOS_MAP_OBJECT);
     102           0 :         req->qmr_mpls_qos = NULL;
     103           0 :         req->qmr_mpls_qos_size = 0;
     104           0 :         if (req->qmr_mpls_qos_fc_id) {
     105           0 :             vr_free(req->qmr_mpls_qos_fc_id, VR_QOS_MAP_OBJECT);
     106           0 :             req->qmr_mpls_qos_fc_id = NULL;
     107           0 :             req->qmr_mpls_qos_fc_id_size = 0;
     108             :         }
     109             :     }
     110             : 
     111           0 :     if (req->qmr_dotonep && req->qmr_dotonep_size) {
     112           0 :         vr_free(req->qmr_dotonep, VR_QOS_MAP_OBJECT);
     113           0 :         req->qmr_dotonep = NULL;
     114           0 :         req->qmr_dotonep_size = 0;
     115           0 :         if (req->qmr_dotonep_fc_id) {
     116           0 :             vr_free(req->qmr_dotonep_fc_id, VR_QOS_MAP_OBJECT);
     117           0 :             req->qmr_dotonep_fc_id = NULL;
     118           0 :             req->qmr_dotonep_fc_id_size = 0;
     119             :         }
     120             :     }
     121             : 
     122           0 :     vr_free(req, VR_QOS_MAP_OBJECT);
     123           0 :     return;
     124             : }
     125             : 
     126             : static vr_qos_map_req *
     127           0 : vr_qos_map_req_get(void)
     128             : {
     129             :     vr_qos_map_req *req;
     130             : 
     131           0 :     req = vr_zalloc(sizeof(vr_qos_map_req), VR_QOS_MAP_OBJECT);
     132           0 :     if (!req)
     133           0 :         return NULL;
     134             : 
     135           0 :     req->qmr_dscp =
     136           0 :         vr_zalloc(sizeof(uint8_t) * VR_DSCP_QOS_ENTRIES, VR_QOS_MAP_OBJECT);
     137           0 :     if (!req->qmr_dscp) {
     138           0 :         goto alloc_failure;
     139             :     }
     140           0 :     req->qmr_dscp_size = VR_DSCP_QOS_ENTRIES;
     141             : 
     142           0 :     req->qmr_dscp_fc_id =
     143           0 :         vr_zalloc(sizeof(uint8_t) * VR_DSCP_QOS_ENTRIES, VR_QOS_MAP_OBJECT);
     144           0 :     if (!req->qmr_dscp_fc_id) {
     145           0 :         goto alloc_failure;
     146             :     }
     147           0 :     req->qmr_dscp_fc_id_size = VR_DSCP_QOS_ENTRIES;
     148             : 
     149           0 :     req->qmr_mpls_qos =
     150           0 :         vr_zalloc(sizeof(uint8_t) * VR_MPLS_QOS_ENTRIES, VR_QOS_MAP_OBJECT);
     151           0 :     if (!req->qmr_mpls_qos) {
     152           0 :         goto alloc_failure;
     153             :     }
     154           0 :     req->qmr_mpls_qos_size = VR_MPLS_QOS_ENTRIES;
     155             : 
     156           0 :     req->qmr_mpls_qos_fc_id =
     157           0 :         vr_zalloc(sizeof(uint8_t) * VR_MPLS_QOS_ENTRIES, VR_QOS_MAP_OBJECT);
     158           0 :     if (!req->qmr_mpls_qos_fc_id) {
     159           0 :         goto alloc_failure;
     160             :     }
     161           0 :     req->qmr_mpls_qos_fc_id_size = VR_MPLS_QOS_ENTRIES;
     162             : 
     163           0 :     req->qmr_dotonep =
     164           0 :         vr_zalloc(sizeof(uint8_t) * VR_DOTONEP_QOS_ENTRIES, VR_QOS_MAP_OBJECT);
     165           0 :     if (!req->qmr_dotonep) {
     166           0 :         goto alloc_failure;
     167             :     }
     168           0 :     req->qmr_dotonep_size = VR_DOTONEP_QOS_ENTRIES;
     169             : 
     170           0 :     req->qmr_dotonep_fc_id =
     171           0 :         vr_zalloc(sizeof(uint8_t) * VR_DOTONEP_QOS_ENTRIES, VR_QOS_MAP_OBJECT);
     172           0 :     if (!req->qmr_dotonep_fc_id) {
     173           0 :         goto alloc_failure;
     174             :     }
     175           0 :     req->qmr_dotonep_fc_id_size = VR_DOTONEP_QOS_ENTRIES;
     176             : 
     177           0 :     return req;
     178             : 
     179           0 : alloc_failure:
     180           0 :     vr_qos_map_req_destroy(req);
     181           0 :     return NULL;
     182             : }
     183             : 
     184             : static void
     185           0 : vr_qos_map_make_req(unsigned int qmrid, vr_qos_map_req *resp,
     186             :         struct vr_forwarding_class *fc_p)
     187             : {
     188             :     unsigned int i;
     189             : 
     190           0 :     resp->qmr_id = qmrid;
     191             : 
     192           0 :     for (i = 0; i < VR_DSCP_QOS_ENTRIES; i++) {
     193           0 :         if (!fc_p[i].vfc_valid)
     194           0 :             continue;
     195             : 
     196           0 :         resp->qmr_dscp[i] = fc_p[i].vfc_dscp;
     197           0 :         resp->qmr_dscp_fc_id[i] = fc_p[i].vfc_id;
     198             :     }
     199             : 
     200           0 :     for (i = 0; i < VR_MPLS_QOS_ENTRIES; i++) {
     201           0 :         if (!fc_p[i].vfc_valid)
     202           0 :             continue;
     203             : 
     204           0 :         resp->qmr_mpls_qos[i] = fc_p[VR_DSCP_QOS_ENTRIES + i].vfc_mpls_qos;
     205           0 :         resp->qmr_mpls_qos_fc_id[i] = fc_p[VR_DSCP_QOS_ENTRIES + i].vfc_id;
     206             :     }
     207             : 
     208           0 :     for (i = 0; i < VR_DOTONEP_QOS_ENTRIES; i++) {
     209           0 :         if (!fc_p[i].vfc_valid)
     210           0 :             continue;
     211             : 
     212           0 :         resp->qmr_dotonep[i] =
     213           0 :             fc_p[VR_DSCP_QOS_ENTRIES + VR_MPLS_QOS_ENTRIES + i].vfc_dotonep_qos;
     214           0 :         resp->qmr_dotonep_fc_id[i] =
     215           0 :             fc_p[VR_DSCP_QOS_ENTRIES + VR_MPLS_QOS_ENTRIES + i].vfc_id;
     216             :     }
     217             : 
     218           0 :     return;
     219             : }
     220             : 
     221             : static void
     222           0 : vr_qos_map_free_fc_cb(struct vrouter *router, void *data)
     223             : {
     224           0 :     struct vr_defer_data *defer = (struct vr_defer_data *)data;
     225             : 
     226           0 :     if (!defer)
     227           0 :         return;
     228             : 
     229           0 :     vr_free(defer->vdd_data, VR_QOS_MAP_OBJECT);
     230           0 :     return;
     231             : }
     232             : 
     233             : static int
     234           0 : vr_qos_map_free_fc_defer(struct vrouter *router,
     235             :         struct vr_forwarding_class *fc_p)
     236             : {
     237             :     struct vr_defer_data *defer;
     238             : 
     239           0 :     defer = vr_get_defer_data(sizeof(*defer));
     240           0 :     if (!defer)
     241           0 :         return -ENOMEM;
     242             : 
     243           0 :     defer->vdd_data = fc_p;
     244           0 :     vr_defer(router, vr_qos_map_free_fc_cb, (void *)defer);
     245             : 
     246           0 :     return 0;
     247             : }
     248             : 
     249             : static void
     250           0 : vr_qos_map_delete(vr_qos_map_req *req)
     251             : {
     252           0 :     int ret = 0;
     253             : 
     254             :     struct vr_forwarding_class *fc_p;
     255           0 :     struct vrouter *router = vrouter_get(req->qmr_rid);
     256             : 
     257           0 :     if (req->qmr_id >= vr_qos_map_entries) {
     258           0 :         ret = -EINVAL;
     259           0 :         goto generate_response;
     260             :     }
     261             : 
     262           0 :     fc_p = vr_qos_map_get_fc(router, req->qmr_id);
     263           0 :     if (!fc_p) {
     264           0 :         ret = 0;
     265           0 :         goto generate_response;
     266             :     }
     267             : 
     268           0 :     vr_qos_map_set_fc(router, req->qmr_id, NULL);
     269           0 :     if (vr_qos_map_free_fc_defer(router, fc_p)) {
     270           0 :         vr_delay_op();
     271           0 :         vr_free(fc_p, VR_QOS_MAP_OBJECT);
     272             :     }
     273             : 
     274           0 :     (void)vr_offload_qos_map_del(req);
     275             : 
     276           0 : generate_response:
     277           0 :     vr_send_response(ret);
     278           0 :     return;
     279             : }
     280             : 
     281             : static void
     282           0 : vr_qos_map_dump(vr_qos_map_req *req)
     283             : {
     284           0 :     int ret = 0;
     285             :     unsigned int i;
     286             : 
     287             :     vr_qos_map_req *resp;
     288             :     struct vr_forwarding_class *fc_p;
     289           0 :     struct vrouter *router = vrouter_get(req->qmr_rid);
     290           0 :     struct vr_message_dumper *dumper = NULL;
     291             : 
     292           0 :     if (req->qmr_marker + 1 >= vr_qos_map_entries)
     293           0 :         goto generate_response;
     294             : 
     295           0 :     dumper = vr_message_dump_init(req);
     296           0 :     if (!dumper) {
     297           0 :         ret = -ENOMEM;
     298           0 :         goto generate_response;
     299             :     }
     300             : 
     301           0 :     for (i = (req->qmr_marker + 1); i < vr_qos_map_entries; i++) {
     302           0 :         fc_p = vr_qos_map_get_fc(router, i);
     303           0 :         if (!fc_p)
     304           0 :             continue;
     305             : 
     306           0 :         resp = vr_qos_map_req_get();
     307           0 :         if (!resp) {
     308           0 :             ret = -ENOMEM;
     309           0 :             goto generate_response;
     310             :         }
     311             : 
     312           0 :         vr_qos_map_make_req(i, resp, fc_p);
     313             : 
     314           0 :         (void)vr_offload_qos_map_get(resp);
     315             : 
     316           0 :         ret = vr_message_dump_object(dumper, VR_QOS_MAP_OBJECT_ID, resp);
     317           0 :         vr_qos_map_req_destroy(resp);
     318           0 :         if (ret <= 0)
     319           0 :             break;
     320             :     }
     321             : 
     322           0 : generate_response:
     323           0 :     vr_message_dump_exit(dumper, ret);
     324           0 :     return;
     325             : }
     326             : 
     327             : static void
     328           0 : vr_qos_map_get(vr_qos_map_req *req)
     329             : {
     330           0 :     int ret = 0;
     331             : 
     332             :     vr_qos_map_req *resp;
     333           0 :     struct vrouter *router = vrouter_get(req->qmr_rid);
     334           0 :     struct vr_forwarding_class *fc_p = NULL;
     335             : 
     336           0 :     if (req->qmr_id >= vr_qos_map_entries) {
     337           0 :         ret = -EINVAL;
     338           0 :         goto get_error;
     339             :     }
     340             : 
     341           0 :     fc_p = vr_qos_map_get_fc(router, req->qmr_id);
     342           0 :     if (!fc_p) {
     343           0 :         ret = -ENOENT;
     344           0 :         goto get_error;
     345             :     }
     346             : 
     347           0 :     resp = vr_qos_map_req_get();
     348           0 :     if (!resp) {
     349           0 :         ret = -ENOMEM;
     350           0 :         goto get_error;
     351             :     }
     352             : 
     353           0 :     vr_qos_map_make_req(req->qmr_id, resp, fc_p);
     354             : 
     355             :     /* Debug comparison to check if matching entry is programmed on NIC */
     356           0 :     (void)vr_offload_qos_map_get(resp);
     357             : 
     358           0 :     vr_message_response(VR_QOS_MAP_OBJECT_ID, resp, ret, false);
     359           0 :     if (resp) {
     360           0 :         vr_qos_map_req_destroy(resp);
     361             :     }
     362             : 
     363           0 :     return;
     364             : 
     365           0 : get_error:
     366           0 :     vr_send_response(ret);
     367           0 :     return;
     368             : }
     369             : 
     370             : static void
     371           0 : vr_qos_map_add(vr_qos_map_req *req)
     372             : {
     373           0 :     int ret = 0;
     374           0 :     bool need_set = false;
     375             :     unsigned int size, i;
     376             : 
     377           0 :     struct vrouter *router = vrouter_get(req->qmr_rid);
     378             :     struct vr_forwarding_class *fc_p, *fc_e;
     379             : 
     380           0 :     ret = vr_qos_map_request_validate(req);
     381           0 :     if (ret) {
     382           0 :         goto generate_response;
     383             :     }
     384             : 
     385           0 :     fc_p = vr_qos_map_get_fc(router, req->qmr_id);
     386           0 :     if (!fc_p) {
     387           0 :         size = vr_qos_map_entry_size * sizeof(struct vr_forwarding_class);
     388           0 :         fc_p = vr_zalloc(size, VR_QOS_MAP_OBJECT);
     389           0 :         if (!fc_p) {
     390           0 :             ret = -ENOMEM;
     391           0 :             goto generate_response;
     392             :         }
     393           0 :         need_set = true;
     394             :     }
     395             : 
     396           0 :     for (i = 0; i < req->qmr_dscp_size; i++) {
     397           0 :         if (req->qmr_dscp[i] >= VR_DSCP_QOS_ENTRIES)
     398           0 :             continue;
     399             : 
     400           0 :         fc_e = &fc_p[req->qmr_dscp[i]];
     401           0 :         fc_e->vfc_dscp = req->qmr_dscp[i];
     402           0 :         fc_e->vfc_id = req->qmr_dscp_fc_id[i];
     403           0 :         fc_e->vfc_valid = 1;
     404             :     }
     405             : 
     406           0 :     for (i = 0; i < req->qmr_mpls_qos_size; i++) {
     407           0 :         if (req->qmr_mpls_qos[i] >= VR_MPLS_QOS_ENTRIES)
     408           0 :             continue;
     409             : 
     410           0 :         fc_e = &fc_p[VR_DSCP_QOS_ENTRIES + req->qmr_mpls_qos[i]];
     411           0 :         fc_e->vfc_mpls_qos = req->qmr_mpls_qos[i];
     412           0 :         fc_e->vfc_id = req->qmr_mpls_qos_fc_id[i];
     413           0 :         fc_e->vfc_valid = 1;
     414             :     }
     415             : 
     416           0 :     for (i = 0; i < req->qmr_dotonep_size; i++) {
     417           0 :         if (req->qmr_dotonep[i] >= VR_DOTONEP_QOS_ENTRIES)
     418           0 :             continue;
     419             : 
     420           0 :         fc_e = &fc_p[VR_DSCP_QOS_ENTRIES + VR_MPLS_QOS_ENTRIES +
     421           0 :             req->qmr_dotonep[i]];
     422           0 :         fc_e->vfc_dotonep_qos = req->qmr_dotonep[i];
     423           0 :         fc_e->vfc_id = req->qmr_dotonep_fc_id[i];
     424           0 :         fc_e->vfc_valid = 1;
     425             :     }
     426             : 
     427           0 :     ret = vr_offload_qos_map_add(req);
     428           0 :     if (ret) {
     429           0 :         vr_printf("offload QoS map not supported - not configuring\n");
     430           0 :         vr_free(fc_p, VR_QOS_MAP_OBJECT);
     431           0 :         goto generate_response;
     432             :     }
     433             : 
     434           0 :     if (need_set) {
     435           0 :         vr_qos_map_set_fc(router, req->qmr_id, fc_p);
     436             :     }
     437             : 
     438           0 : generate_response:
     439           0 :     vr_send_response(ret);
     440           0 :     return;
     441             : }
     442             : 
     443             : void
     444           0 : vr_qos_map_req_process(void *s_req)
     445             : {
     446           0 :     vr_qos_map_req *req = (vr_qos_map_req *)s_req;
     447             : 
     448           0 :     switch (req->h_op) {
     449           0 :     case SANDESH_OP_ADD:
     450           0 :         vr_qos_map_add(req);
     451           0 :         break;
     452             : 
     453           0 :     case SANDESH_OP_GET:
     454           0 :         vr_qos_map_get(req);
     455           0 :         break;
     456             : 
     457           0 :     case SANDESH_OP_DUMP:
     458           0 :         vr_qos_map_dump(req);
     459           0 :         break;
     460             : 
     461           0 :     case SANDESH_OP_DEL:
     462           0 :         vr_qos_map_delete(req);
     463           0 :         break;
     464             : 
     465           0 :     default:
     466           0 :         vr_qos_message_error(-EINVAL);
     467           0 :         break;
     468             :     }
     469             : 
     470           0 :     return;
     471             : }
     472             : 
     473             : static struct vr_forwarding_class *
     474           0 : vr_fc_map_get_fc(struct vrouter *router, unsigned int i)
     475             : {
     476           0 :     if (i >= vr_fc_map_entries)
     477           0 :         return NULL;
     478             : 
     479           0 :     return &router->vr_fc_table[i];
     480             : }
     481             : 
     482             : static void
     483           0 : vr_fc_map_req_destroy(vr_fc_map_req *req)
     484             : {
     485           0 :     if (!req)
     486           0 :         return;
     487             : 
     488           0 :     if (req->fmr_id) {
     489           0 :         vr_free(req->fmr_id, VR_FC_OBJECT);
     490           0 :         req->fmr_id_size = 0;
     491             :     }
     492             : 
     493           0 :     if (req->fmr_dscp) {
     494           0 :         vr_free(req->fmr_dscp, VR_FC_OBJECT);
     495           0 :         req->fmr_dscp_size = 0;
     496             :     }
     497             : 
     498           0 :     if (req->fmr_mpls_qos) {
     499           0 :         vr_free(req->fmr_mpls_qos, VR_FC_OBJECT);
     500           0 :         req->fmr_mpls_qos_size = 0;
     501             :     }
     502             : 
     503           0 :     if (req->fmr_dotonep) {
     504           0 :         vr_free(req->fmr_dotonep, VR_FC_OBJECT);
     505           0 :         req->fmr_dotonep_size = 0;
     506             :     }
     507             : 
     508           0 :     if (req->fmr_queue_id) {
     509           0 :         vr_free(req->fmr_queue_id, VR_FC_OBJECT);
     510           0 :         req->fmr_queue_id_size = 0;
     511             :     }
     512             : 
     513           0 :     vr_free(req, VR_FC_OBJECT);
     514           0 :     return;
     515             : }
     516             : 
     517             : static vr_fc_map_req *
     518           0 : vr_fc_map_req_get(unsigned int entries)
     519             : {
     520             :     vr_fc_map_req *req;
     521             : 
     522           0 :     req = vr_zalloc(sizeof(*req), VR_FC_OBJECT);
     523           0 :     if (!req)
     524           0 :         return NULL;
     525             : 
     526           0 :     req->fmr_id = vr_zalloc(entries, VR_FC_OBJECT);
     527           0 :     if (!req->fmr_id) {
     528           0 :         goto error;
     529             :     }
     530           0 :     req->fmr_id_size = entries;
     531             : 
     532           0 :     req->fmr_dscp = vr_zalloc(entries, VR_FC_OBJECT);
     533           0 :     if (!req->fmr_dscp) {
     534           0 :         goto error;
     535             :     }
     536           0 :     req->fmr_dscp_size = entries;
     537             : 
     538           0 :     req->fmr_mpls_qos = vr_zalloc(entries, VR_FC_OBJECT);
     539           0 :     if (!req->fmr_mpls_qos) {
     540           0 :         goto error;
     541             :     }
     542           0 :     req->fmr_mpls_qos_size = entries;
     543             : 
     544           0 :     req->fmr_dotonep = vr_zalloc(entries, VR_FC_OBJECT);
     545           0 :     if (!req->fmr_dotonep) {
     546           0 :         goto error;
     547             :     }
     548           0 :     req->fmr_dotonep_size = entries;
     549             : 
     550           0 :     req->fmr_queue_id = vr_zalloc(entries, VR_FC_OBJECT);
     551           0 :     if (!req->fmr_queue_id) {
     552           0 :         goto error;
     553             :     }
     554           0 :     req->fmr_queue_id_size = entries;
     555             : 
     556           0 :     return req;
     557             : 
     558           0 : error:
     559           0 :     vr_fc_map_req_destroy(req);
     560           0 :     return NULL;
     561             : }
     562             : 
     563             : static void
     564           0 : vr_fc_map_delete(vr_fc_map_req *req)
     565             : {
     566           0 :     int ret = 0;
     567             : 
     568           0 :     struct vrouter *router = vrouter_get(req->fmr_rid);
     569             :     struct vr_forwarding_class *fc_p;
     570             : 
     571           0 :     if (!req->fmr_id) {
     572           0 :         ret = -EINVAL;
     573           0 :         goto generate_response;
     574             :     }
     575             : 
     576           0 :     if (req->fmr_id[0] >= vr_fc_map_entries) {
     577           0 :         ret = -EINVAL;
     578           0 :         goto generate_response;
     579             :     }
     580             : 
     581           0 :     fc_p = vr_fc_map_get_fc(router, req->fmr_id[0]);
     582           0 :     if (!fc_p) {
     583           0 :         ret = -EINVAL;
     584           0 :         goto generate_response;
     585             :     }
     586             : 
     587           0 :     memset(fc_p, 0, sizeof(*fc_p));
     588           0 :     (void)vr_offload_fc_map_del(req);
     589           0 :     vr_send_response(0);
     590             : 
     591           0 :     return;
     592             : 
     593           0 : generate_response:
     594           0 :     vr_send_response(ret);
     595           0 :     return;
     596             : }
     597             : 
     598             : static void
     599           0 : vr_fc_map_dump(vr_fc_map_req *req)
     600             : {
     601           0 :     int ret = 0;
     602             :     unsigned int i;
     603             : 
     604             :     vr_fc_map_req *resp;
     605             :     struct vr_forwarding_class *fc_p;
     606           0 :     struct vrouter *router = vrouter_get(req->fmr_rid);
     607           0 :     struct vr_message_dumper *dumper = NULL;
     608             : 
     609           0 :     if (req->fmr_marker + 1 >= vr_fc_map_entries)
     610           0 :         goto generate_response;
     611             : 
     612           0 :     dumper = vr_message_dump_init(req);
     613           0 :     if (!dumper) {
     614           0 :         ret = -ENOMEM;
     615           0 :         goto generate_response;
     616             :     }
     617             : 
     618           0 :     for (i = (req->fmr_marker + 1); i < vr_fc_map_entries; i++) {
     619           0 :         fc_p = vr_fc_map_get_fc(router, i);
     620           0 :         if (!fc_p || !fc_p->vfc_valid)
     621           0 :             continue;
     622             : 
     623           0 :         resp = vr_fc_map_req_get(1);
     624           0 :         if (!resp) {
     625           0 :             ret = -ENOMEM;
     626           0 :             goto generate_response;
     627             :         }
     628             : 
     629           0 :         resp->fmr_id[0] = i;
     630           0 :         resp->fmr_dscp[0] = fc_p->vfc_dscp;
     631           0 :         resp->fmr_mpls_qos[0] = fc_p->vfc_mpls_qos;
     632           0 :         resp->fmr_dotonep[0] = fc_p->vfc_dotonep_qos;
     633           0 :         resp->fmr_queue_id[0] = fc_p->vfc_queue_id;
     634             : 
     635           0 :         (void)vr_offload_fc_map_get(resp);
     636             : 
     637           0 :         ret = vr_message_dump_object(dumper, VR_FC_MAP_OBJECT_ID, resp);
     638           0 :         vr_fc_map_req_destroy(resp);
     639           0 :         if (ret <= 0)
     640           0 :             break;
     641             :     }
     642             : 
     643           0 : generate_response:
     644           0 :     vr_message_dump_exit(dumper, ret);
     645           0 :     return;
     646             : }
     647             : 
     648             : static void
     649           0 : vr_fc_map_get(vr_fc_map_req *req)
     650             : {
     651           0 :     int ret = 0;
     652             : 
     653           0 :     vr_fc_map_req *resp = NULL;
     654           0 :     struct vrouter *router = vrouter_get(req->fmr_rid);
     655             :     struct vr_forwarding_class *fc_p;
     656             : 
     657           0 :     if (!req->fmr_id) {
     658           0 :         ret = -EINVAL;
     659           0 :         goto generate_response;
     660             :     }
     661             : 
     662           0 :     if (req->fmr_id[0] >= vr_fc_map_entries) {
     663           0 :         ret = -EINVAL;
     664           0 :         goto generate_response;
     665             :     }
     666             : 
     667           0 :     fc_p = vr_fc_map_get_fc(router, req->fmr_id[0]);
     668           0 :     if (!fc_p || !fc_p->vfc_valid) {
     669           0 :         ret = -ENOENT;
     670           0 :         goto generate_response;
     671             :     }
     672             : 
     673           0 :     resp = vr_fc_map_req_get(1);
     674           0 :     if (!resp) {
     675           0 :         ret = -ENOMEM;
     676           0 :         goto generate_response;
     677             :     }
     678             : 
     679           0 :     resp->fmr_id[0] = req->fmr_id[0];
     680           0 :     resp->fmr_dscp[0] = fc_p->vfc_dscp;
     681           0 :     resp->fmr_mpls_qos[0] = fc_p->vfc_mpls_qos;
     682           0 :     resp->fmr_dotonep[0] = fc_p->vfc_dotonep_qos;
     683           0 :     resp->fmr_queue_id[0] = fc_p->vfc_queue_id;
     684             : 
     685             :     /* Debug comparison to check if matching entry is programmed on NIC */
     686           0 :     (void)vr_offload_fc_map_get(resp);
     687             : 
     688           0 : generate_response:
     689           0 :     vr_message_response(VR_FC_MAP_OBJECT_ID, ret < 0 ? NULL : resp, ret, false);
     690           0 :     if (resp)
     691           0 :         vr_fc_map_req_destroy(resp);
     692             : 
     693           0 :     return;
     694             : }
     695             : 
     696             : static void
     697           0 : vr_fc_map_add(vr_fc_map_req *req)
     698             : {
     699           0 :     int ret = 0;
     700             :     unsigned int i;
     701             : 
     702           0 :     struct vrouter *router = vrouter_get(req->fmr_rid);
     703             :     struct vr_forwarding_class *fc_p;
     704             : 
     705           0 :     if (!req->fmr_id || !req->fmr_id_size ||
     706           0 :             !req->fmr_dscp || !req->fmr_dscp_size ||
     707           0 :             !req->fmr_mpls_qos || !req->fmr_mpls_qos_size ||
     708           0 :             !req->fmr_dotonep || !req->fmr_dotonep_size ||
     709           0 :             !req->fmr_queue_id || !req->fmr_queue_id_size) {
     710           0 :         ret = -EINVAL;
     711           0 :         goto generate_response;
     712             :     }
     713             : 
     714           0 :     for (i = 0; i < req->fmr_id_size; i++) {
     715           0 :         fc_p = vr_fc_map_get_fc(router, req->fmr_id[i]);
     716           0 :         if (!fc_p) {
     717           0 :             ret = -EINVAL;
     718           0 :             goto generate_response;
     719             :         }
     720             : 
     721           0 :         fc_p->vfc_id = req->fmr_id[i];
     722           0 :         fc_p->vfc_dscp = req->fmr_dscp[i];
     723           0 :         fc_p->vfc_mpls_qos = req->fmr_mpls_qos[i];
     724           0 :         fc_p->vfc_dotonep_qos = req->fmr_dotonep[i];
     725           0 :         fc_p->vfc_queue_id = req->fmr_queue_id[i];
     726           0 :         fc_p->vfc_valid = 1;
     727             :     }
     728             : 
     729           0 :     ret = vr_offload_fc_map_add(req);
     730           0 :     if (ret) {
     731           0 :         vr_printf("offload FC map not supported - not configuring\n");
     732           0 :         for (i = 0; i < req->fmr_id_size; i++) {
     733           0 :             fc_p = vr_fc_map_get_fc(router, req->fmr_id[i]);
     734           0 :             if (fc_p)
     735           0 :                 memset(fc_p, 0, sizeof(*fc_p));
     736             :         }
     737             :     }
     738             : 
     739           0 : generate_response:
     740           0 :     vr_send_response(ret);
     741           0 :     return;
     742             : }
     743             : 
     744             : void
     745           0 : vr_fc_map_req_process(void *s_req)
     746             : {
     747           0 :     vr_fc_map_req *req = (vr_fc_map_req *)s_req;
     748             : 
     749           0 :     switch (req->h_op) {
     750           0 :     case SANDESH_OP_ADD:
     751           0 :         vr_fc_map_add(req);
     752           0 :         break;
     753             : 
     754           0 :     case SANDESH_OP_GET:
     755           0 :         vr_fc_map_get(req);
     756           0 :         break;
     757             : 
     758           0 :     case SANDESH_OP_DUMP:
     759           0 :         vr_fc_map_dump(req);
     760           0 :         break;
     761             : 
     762           0 :     case SANDESH_OP_DEL:
     763           0 :         vr_fc_map_delete(req);
     764           0 :         break;
     765             : 
     766           0 :     default:
     767           0 :         vr_qos_message_error(-EINVAL);
     768           0 :         break;
     769             :     }
     770             : 
     771           0 :     return;
     772             : }
     773             : 
     774             : struct vr_forwarding_class_qos *
     775          79 : vr_qos_get_forwarding_class(struct vrouter *router, struct vr_packet *pkt,
     776             :         struct vr_forwarding_md *fmd)
     777             : {
     778             :     int8_t tos;
     779          79 :     int16_t qos_id = -1;
     780             :     unsigned int fc_id;
     781             : 
     782             :     struct vr_interface *vif;
     783             :     struct vr_forwarding_class *fc_p;
     784             : 
     785          79 :     vif = pkt->vp_if;
     786             : 
     787          79 :     if (fmd->fmd_flow_index >= 0) {
     788          21 :         qos_id = vr_flow_get_qos(router, pkt, fmd);
     789             :     }
     790             : 
     791          79 :     if (qos_id < 0) {
     792          79 :         qos_id = vif->vif_qos_map_index;
     793             :     }
     794             : 
     795          79 :     if (qos_id >= 0) {
     796          79 :         fc_p = vr_qos_map_get_fc(router, qos_id);
     797          79 :         if (!fc_p)
     798          79 :             return NULL;
     799             : 
     800           0 :         if (pkt->vp_type == VP_TYPE_IP || pkt->vp_type == VP_TYPE_IP6) {
     801           0 :             tos = fmd->fmd_dscp;
     802             :         } else {
     803           0 :             tos = fmd->fmd_dotonep;
     804           0 :             if (tos >= 0)
     805           0 :                 tos += VR_DSCP_QOS_ENTRIES + VR_MPLS_QOS_ENTRIES;
     806             :         }
     807             : 
     808           0 :         if (tos >= 0) {
     809           0 :             fc_id = fc_p[tos].vfc_id;
     810           0 :             fc_p = vr_fc_map_get_fc(router, fc_id);
     811           0 :             if (!fc_p->vfc_valid)
     812           0 :                 return NULL;
     813             : 
     814           0 :             return &fc_p->vfc_qos;
     815             :         }
     816             :     }
     817             : 
     818           0 :     return NULL;
     819             : }
     820             : 
     821             : void
     822          53 : vr_qos_exit(struct vrouter *router, bool soft_reset)
     823             : {
     824             :     unsigned int i;
     825             :     unsigned long size;
     826             : 
     827          53 :     if (soft_reset) {
     828           0 :         size = vr_qos_map_entries * sizeof(struct vr_forwarding_class *);
     829           0 :         if (router->vr_qos_map) {
     830           0 :             memset(router->vr_qos_map, 0, size);
     831             :         }
     832           0 :         size = vr_fc_map_entries * sizeof(struct vr_forwarding_class);
     833           0 :         if (router->vr_fc_table) {
     834           0 :             memset(router->vr_fc_table, 0, size);
     835             :         }
     836             :     } else {
     837          53 :         if (router->vr_qos_map) {
     838      217141 :             for (i = 0; i < vr_qos_map_entries; i++) {
     839      217088 :                 if (router->vr_qos_map[i]) {
     840           0 :                     vr_free(router->vr_qos_map[i], VR_QOS_MAP_OBJECT);
     841           0 :                     router->vr_qos_map[i] = NULL;
     842             :                 }
     843             :             }
     844          53 :             vr_free(router->vr_qos_map, VR_QOS_MAP_OBJECT);
     845          53 :             router->vr_qos_map = NULL;
     846             :         }
     847             : 
     848          53 :         if (router->vr_fc_table) {
     849          53 :             vr_free(router->vr_fc_table, VR_FC_OBJECT);
     850          53 :             router->vr_fc_table = NULL;
     851             :         }
     852             :     }
     853             : 
     854          53 :     return;
     855             : }
     856             : 
     857             : int
     858          53 : vr_qos_init(struct vrouter *router)
     859             : {
     860             :     unsigned long size;
     861             : 
     862          53 :     if (!router->vr_qos_map) {
     863          53 :         size = vr_qos_map_entries * sizeof(struct vr_forwarding_class *);
     864          53 :         router->vr_qos_map = vr_zalloc(size, VR_QOS_MAP_OBJECT);
     865          53 :         if (!router->vr_qos_map) {
     866           0 :             return vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, size);
     867             :         }
     868             :     }
     869             : 
     870          53 :     if (!router->vr_fc_table) {
     871          53 :         size = vr_fc_map_entries * sizeof(struct vr_forwarding_class);
     872          53 :         router->vr_fc_table = vr_zalloc(size, VR_FC_OBJECT);
     873          53 :         if (!router->vr_fc_table) {
     874           0 :             return vr_module_error(-ENOMEM, __FUNCTION__, __LINE__, size);
     875             :         }
     876             :     }
     877             : 
     878          53 :     return 0;
     879             : }

Generated by: LCOV version 1.14