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

Generated by: LCOV version 1.14