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

Generated by: LCOV version 1.14