LCOV - code coverage report
Current view: top level - root/contrail/vrouter/dp-core - vr_message.c (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 124 202 61.4 %
Date: 2026-08-03 02:19:58 Functions: 17 22 77.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * vr_message.c -- message protocol and transport independent interface for
       3             :  * vrouter
       4             :  *
       5             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       6             :  */
       7             : #include <vr_os.h>
       8             : #include <vrouter.h>
       9             : #include "vr_message.h"
      10             : 
      11             : static char *
      12           0 : vr_message_default_malloc(unsigned int size)
      13             : {
      14           0 :     return vr_malloc(size, VR_MESSAGE_OBJECT);
      15             : }
      16             : 
      17             : static void
      18           0 : vr_message_default_free(char *buf)
      19             : {
      20           0 :     if (buf)
      21           0 :         vr_free(buf, VR_MESSAGE_OBJECT);
      22           0 :     return;
      23             : }
      24             : 
      25             : static struct vr_mtransport default_transport = {
      26             :     .mtrans_alloc       =   vr_message_default_malloc,
      27             :     .mtrans_free        =   vr_message_default_free,
      28             : };
      29             : 
      30             : static struct vr_message_handler message_h = {
      31             :     .vm_trans           =   &default_transport,
      32             : };
      33             : 
      34             : void *
      35           0 : vr_mtrans_alloc(unsigned int size)
      36             : {
      37           0 :     if (!message_h.vm_trans)
      38           0 :         return NULL;
      39             : 
      40           0 :     return message_h.vm_trans->mtrans_alloc(size);
      41             : }
      42             : 
      43             : void
      44        2863 : vr_mtrans_free(void *buf)
      45             : {
      46        2863 :     if (!message_h.vm_trans)
      47           0 :         return;
      48             : 
      49        2863 :     message_h.vm_trans->mtrans_free(buf);
      50        2863 :     return;
      51             : }
      52             : 
      53             : int
      54        2862 : vr_message_request(struct vr_message *message)
      55             : {
      56             :     int ret;
      57             : 
      58        2862 :     if (!message_h.vm_proto)
      59           0 :         return 0;
      60             : 
      61        2862 :     if (vr_not_ready)
      62           0 :         return -ENETRESET;
      63             : 
      64        2862 :     if (vr_not_ready)
      65           0 :         return -EBADFD;
      66             : 
      67        2862 :     ret = message_h.vm_proto->mproto_decode(message->vr_message_buf,
      68             :             message->vr_message_len, NULL, NULL);
      69        2862 :     if (ret < 0)
      70           0 :         return ret;
      71             : 
      72        2862 :     return 0;
      73             : }
      74             : 
      75             : uint32_t g_counter = 0;
      76             : static int
      77        2863 : vr_message_queue_response(char *buf, int len, bool broadcast)
      78             : {
      79             :     struct vr_message *response;
      80             : 
      81        2863 :     response = vr_zalloc(sizeof(*response), VR_MESSAGE_RESPONSE_OBJECT);
      82        2863 :     if (!response)
      83           0 :         return -ENOMEM;
      84             : 
      85        2863 :     response->vr_message_buf = buf;
      86        2863 :     response->vr_message_len = len;
      87        2863 :     response->vr_message_broadcast = broadcast;
      88        2863 :     vr_queue_enqueue(&message_h.vm_response_queue,
      89             :             &response->vr_message_queue);
      90             : 
      91        2863 :     return 0;
      92             : }
      93             : 
      94             : struct vr_message *
      95        5725 : vr_message_dequeue_response(void)
      96             : {
      97             :     struct vr_qelem *elem;
      98             : 
      99        5725 :     elem = vr_queue_dequeue(&message_h.vm_response_queue);
     100        5725 :     if (elem)
     101        2863 :         return CONTAINER_OF(vr_message_queue, struct vr_message, elem);
     102             : 
     103        2862 :     return NULL;
     104             : }
     105             : 
     106             : bool
     107        2863 : vr_response_queue_empty(void)
     108             : {
     109        2863 :     return vr_queue_empty(&message_h.vm_response_queue);
     110             : }
     111             : 
     112             : void
     113        2863 : vr_message_free(struct vr_message *message)
     114             : {
     115        2863 :     if (message) {
     116        2863 :         if (message->vr_message_buf)
     117        2863 :             vr_mtrans_free(message->vr_message_buf);
     118        2863 :         vr_free(message, VR_MESSAGE_RESPONSE_OBJECT);
     119             :     }
     120             : 
     121        2863 :     return;
     122             : }
     123             : 
     124             : int
     125           0 : vr_message_make_request(unsigned int object_type, void *object)
     126             : {
     127           0 :     char *buf = NULL;
     128             :     int ret;
     129             :     unsigned int len;
     130             :     struct vr_mproto *proto;
     131             :     struct vr_mtransport *trans;
     132             :     struct vr_message request;
     133             : 
     134           0 :     proto = message_h.vm_proto;
     135           0 :     trans = message_h.vm_trans;
     136           0 :     if (!proto || !trans)
     137           0 :         return 0;
     138             : 
     139           0 :     len = proto->mproto_buf_len(object_type, object);
     140           0 :     buf = trans->mtrans_alloc(len);
     141           0 :     if (!buf)
     142           0 :         return -ENOMEM;
     143             : 
     144           0 :     ret = proto->mproto_encode(buf, len, object_type, object,
     145             :             VR_MESSAGE_TYPE_REQUEST);
     146           0 :     if (ret < 0)
     147           0 :         goto request_fail;
     148             : 
     149           0 :     request.vr_message_buf = buf;
     150           0 :     request.vr_message_len = ret;
     151             : 
     152           0 :     vr_message_request(&request);
     153             : 
     154           0 : request_fail:
     155           0 :     if (buf)
     156           0 :         trans->mtrans_free(buf);
     157             : 
     158           0 :     return ret;
     159             : }
     160             : 
     161             : int
     162           0 : vr_message_process_response(int (*cb)(void *, unsigned int, void *),
     163             :         void *cb_arg)
     164             : {
     165             :     struct vr_message *response;
     166             :     struct vr_mproto *proto;
     167             :     struct vr_mtransport *trans;
     168             : 
     169           0 :     proto = message_h.vm_proto;
     170           0 :     trans = message_h.vm_trans;
     171           0 :     if (!proto || !trans)
     172           0 :         return 0;
     173             : 
     174           0 :     while ((response = vr_message_dequeue_response())) {
     175           0 :         proto->mproto_decode(response->vr_message_buf,
     176             :                 response->vr_message_len, cb, cb_arg);
     177           0 :         vr_message_free(response);
     178             :     }
     179             : 
     180           0 :     return 0;
     181             : }
     182             : 
     183             : int
     184         158 : vr_message_multi_response(struct vr_message_multi *objects)
     185             : {
     186         158 :     char *buf = NULL;
     187         158 :     int ret = 0;
     188         158 :     unsigned int i, buf_len = 0, len = 0;
     189         158 :     struct vr_mproto *proto = NULL;
     190         158 :     struct vr_mtransport *trans = NULL;
     191             : 
     192         158 :     if ((!objects) ||
     193         158 :             (objects->vr_mm_object_count >= VR_MESSAGE_MULTI_MAX_OBJECTS))
     194           0 :         goto response_fail;
     195             : 
     196         158 :     proto = message_h.vm_proto;
     197         158 :     trans = message_h.vm_trans;
     198         158 :     if (!proto || !trans)
     199           0 :         goto response_fail;
     200             : 
     201             : 
     202         474 :     for (i = 0; i < objects->vr_mm_object_count; i++) {
     203         316 :         buf_len += proto->mproto_buf_len(objects->vr_mm_object_type[i],
     204             :                 objects->vr_mm_object[i]);
     205             :     }
     206             : 
     207         158 :     if (!buf_len)
     208           0 :         goto response_fail;
     209             : 
     210         158 :     buf = trans->mtrans_alloc(buf_len);
     211         158 :     if (!buf) {
     212           0 :         ret = -ENOMEM;
     213           0 :         goto response_fail;
     214             :     }
     215             : 
     216         474 :     for (i = 0; i < objects->vr_mm_object_count; i++) {
     217         316 :         ret = proto->mproto_encode(buf + len, buf_len - len, objects->vr_mm_object_type[i],
     218             :                             objects->vr_mm_object[i], VR_MESSAGE_TYPE_RESPONSE);
     219         316 :         if (ret < 0)
     220           0 :             goto response_fail;
     221             : 
     222         316 :         len += ret;
     223             :     }
     224             : 
     225         158 :     return vr_message_queue_response(buf, len, false);
     226             : 
     227           0 : response_fail:
     228           0 :     if (trans && buf)
     229           0 :         trans->mtrans_free(buf);
     230           0 :     vr_send_response(ret);
     231             : 
     232           0 :     return ret;
     233             : 
     234             : }
     235             : 
     236             : int
     237        2704 : vr_message_response(unsigned int object_type, void *object, int ret, bool broadcast)
     238             : {
     239        2704 :     char *buf = NULL;
     240        2704 :     unsigned int len = 0;
     241             :     struct vr_mproto *proto;
     242             :     struct vr_mtransport *trans;
     243             : 
     244        2704 :     proto = message_h.vm_proto;
     245        2704 :     trans = message_h.vm_trans;
     246        2704 :     if (!proto || !trans)
     247           0 :         return 0;
     248             : 
     249             : 
     250        2704 :     len = proto->mproto_buf_len(object_type, object);
     251        2704 :     len += proto->mproto_buf_len(VR_RESPONSE_OBJECT_ID, NULL);
     252             : 
     253        2704 :     buf = trans->mtrans_alloc(len);
     254        2704 :     if (!buf)
     255           0 :         return -ENOMEM;
     256             : 
     257        2704 :     ret = proto->mproto_encode_response(buf, len, object_type,
     258             :             object, ret);
     259        2704 :     if (ret < 0)
     260           0 :         goto response_fail;
     261             : 
     262        2704 :     return vr_message_queue_response(buf, ret, broadcast);
     263             : 
     264           0 : response_fail:
     265           0 :     if (buf)
     266           0 :         trans->mtrans_free(buf);
     267             : 
     268           0 :     vr_send_response(ret);
     269           0 :     return ret;
     270             : }
     271             : 
     272             : int
     273        1994 : vr_send_response(int code)
     274             : {
     275        1994 :     return vr_message_response(VR_NULL_OBJECT_ID, NULL, code, false);
     276             : }
     277             : 
     278             : int
     279         709 : vr_send_broadcast(unsigned int object_type, void *object, unsigned int sandesh_op, int code)
     280             : {
     281         709 :     if (!vr_nl_broadcast_supported)
     282         709 :       return 0;
     283             :     // We only broadcast requests that have succeeded
     284           0 :     if (code >= 0)
     285           0 :         return vr_message_response(object_type, object, code, true);
     286           0 :     return code;
     287             : }
     288             : 
     289             : int
     290           1 : vr_message_dump_object(void *arg, unsigned int object_type, void *object)
     291             : {
     292             :     int ret;
     293             :     struct vr_mproto *proto;
     294             :     struct vr_mtransport *trans;
     295           1 :     struct vr_message_dumper *dumper = (struct vr_message_dumper *)arg;
     296             : 
     297           1 :     proto = message_h.vm_proto;
     298           1 :     trans = message_h.vm_trans;
     299           1 :     if (!proto || !trans)
     300           0 :         return 0;
     301             : 
     302           1 :     ret = proto->mproto_encode(dumper->dump_buffer + dumper->dump_offset,
     303           1 :             dumper->dump_buf_len - dumper->dump_offset,
     304             :             object_type, object, VR_MESSAGE_TYPE_RESPONSE);
     305           1 :     if (ret < 0) {
     306             :         /* we have more to dump, but we have to exit early */
     307           0 :         dumper->dump_num_dumped |= VR_MESSAGE_DUMP_INCOMPLETE;
     308           0 :         return ret;
     309             :     }
     310             : 
     311           1 :     dumper->dump_offset += ret;
     312           1 :     dumper->dump_num_dumped++;
     313           1 :     return ret;
     314             : }
     315             : 
     316             : void
     317           1 : vr_message_dump_exit(void *context, int ret)
     318             : {
     319             :     struct vr_mproto *proto;
     320             :     struct vr_mtransport *trans;
     321           1 :     struct vr_message_dumper *dumper = (struct vr_message_dumper *)context;
     322             : 
     323           1 :     proto = message_h.vm_proto;
     324           1 :     trans = message_h.vm_trans;
     325           1 :     if (!proto || !trans)
     326           0 :         return;
     327             : 
     328           1 :     if (dumper)
     329           1 :         ret = dumper->dump_num_dumped;
     330             : 
     331           1 :     vr_send_response(ret);
     332             : 
     333           1 :     if (dumper) {
     334           1 :         if (!dumper->dump_offset) {
     335           0 :             if (dumper->dump_buffer)
     336           0 :                 trans->mtrans_free(dumper->dump_buffer);
     337             :         } else
     338           1 :             vr_message_queue_response(dumper->dump_buffer,
     339           1 :               dumper->dump_offset, false);
     340             : 
     341           1 :         vr_free(dumper, VR_MESSAGE_DUMP_OBJECT);
     342             :     }
     343             : 
     344           1 :     return;
     345             : }
     346             : 
     347             : struct vr_message_dumper *
     348           1 : vr_message_dump_init(void *req)
     349             : {
     350             :     char *buf;
     351             :     struct vr_message_dumper *dumper;
     352             :     struct vr_mproto *proto;
     353             :     struct vr_mtransport *trans;
     354             : 
     355           1 :     proto = message_h.vm_proto;
     356           1 :     trans = message_h.vm_trans;
     357           1 :     if (!proto || !trans)
     358           0 :         return NULL;
     359             : 
     360           1 :     dumper = vr_zalloc(sizeof(*dumper), VR_MESSAGE_DUMP_OBJECT);
     361           1 :     if (!dumper)
     362           0 :         return NULL;
     363             : 
     364           1 :     buf = trans->mtrans_alloc(VR_MESSAGE_PAGE_SIZE);
     365           1 :     if (!buf) {
     366           0 :         vr_free(dumper, VR_MESSAGE_DUMP_OBJECT);
     367           0 :         return NULL;
     368             :     }
     369             : 
     370           1 :     dumper->dump_buffer = buf;
     371           1 :     dumper->dump_buf_len = VR_MESSAGE_PAGE_SIZE;
     372           1 :     dumper->dump_offset = 0;
     373           1 :     dumper->dump_req = req;
     374             : 
     375           1 :     return dumper;
     376             : }
     377             : 
     378             : void
     379          53 : vr_message_transport_unregister(struct vr_mtransport *trans)
     380             : {
     381          53 :     if (message_h.vm_trans == trans)
     382          53 :         message_h.vm_trans = NULL;
     383             : 
     384          53 :     return;
     385             : }
     386             : 
     387             : int
     388          53 : vr_message_transport_register(struct vr_mtransport *trans)
     389             : {
     390          53 :     message_h.vm_trans = trans;
     391          53 :     return 0;
     392             : }
     393             : 
     394             : void
     395          53 : vr_message_proto_unregister(struct vr_mproto *proto)
     396             : {
     397          53 :     if (message_h.vm_proto == proto)
     398          53 :         message_h.vm_proto = NULL;
     399             : 
     400          53 :     return;
     401             : }
     402             : 
     403             : int
     404          53 : vr_message_proto_register(struct vr_mproto *proto)
     405             : {
     406          53 :     if (message_h.vm_proto)
     407           0 :         return -EEXIST;
     408             : 
     409          53 :     message_h.vm_proto = proto;
     410          53 :     return 0;
     411             : }
     412             : 

Generated by: LCOV version 1.14