vrrp: fix vrrp_garp_or_na_send()'s memory leak
[vpp.git] / src / plugins / vrrp / vrrp_api.c
index 3b9c256..e31e0a7 100644 (file)
 #include <vrrp/vrrp.api_enum.h>
 #include <vrrp/vrrp.api_types.h>
 
-#define REPLY_MSG_ID_BASE vmp->msg_id_base
+#define REPLY_MSG_ID_BASE vrrp_main.msg_id_base
 #include <vlibapi/api_helper_macros.h>
 
 /* API message handlers */
+static void
+vl_api_vrrp_vr_update_t_handler (vl_api_vrrp_vr_update_t *mp)
+{
+  vl_api_vrrp_vr_update_reply_t *rmp;
+  vrrp_vr_config_t vr_conf;
+  u32 api_flags;
+  u32 vrrp_index = INDEX_INVALID;
+  ip46_address_t *addrs = 0;
+  int rv;
+
+  VALIDATE_SW_IF_INDEX (mp);
+
+  api_flags = htonl (mp->flags);
+
+  clib_memset (&vr_conf, 0, sizeof (vr_conf));
+
+  vr_conf.sw_if_index = ntohl (mp->sw_if_index);
+  vr_conf.vr_id = mp->vr_id;
+  vr_conf.priority = mp->priority;
+  vr_conf.adv_interval = ntohs (mp->interval);
+
+  if (api_flags & VRRP_API_VR_PREEMPT)
+    vr_conf.flags |= VRRP_VR_PREEMPT;
+
+  if (api_flags & VRRP_API_VR_ACCEPT)
+    vr_conf.flags |= VRRP_VR_ACCEPT;
+
+  if (api_flags & VRRP_API_VR_UNICAST)
+    vr_conf.flags |= VRRP_VR_UNICAST;
+
+  if (api_flags & VRRP_API_VR_IPV6)
+    vr_conf.flags |= VRRP_VR_IPV6;
+
+  int i;
+  for (i = 0; i < mp->n_addrs; i++)
+    {
+      ip46_address_t *addr;
+      void *src, *dst;
+      int len;
+
+      vec_add2 (addrs, addr, 1);
+
+      if (ntohl (mp->addrs[i].af) == ADDRESS_IP4)
+       {
+         src = &mp->addrs[i].un.ip4;
+         dst = &addr->ip4;
+         len = sizeof (addr->ip4);
+       }
+      else
+       {
+         src = &mp->addrs[i].un.ip6;
+         dst = &addr->ip6;
+         len = sizeof (addr->ip6);
+       }
+
+      clib_memcpy (dst, src, len);
+    }
+
+  vr_conf.vr_addrs = addrs;
+
+  if (vr_conf.priority == 0)
+    {
+      clib_warning ("VR priority must be > 0");
+      rv = VNET_API_ERROR_INVALID_VALUE;
+    }
+  else if (vr_conf.adv_interval == 0)
+    {
+      clib_warning ("VR advertisement interval must be > 0");
+      rv = VNET_API_ERROR_INVALID_VALUE;
+    }
+  else if (vr_conf.vr_id == 0)
+    {
+      clib_warning ("VR ID must be > 0");
+      rv = VNET_API_ERROR_INVALID_VALUE;
+    }
+  else
+    {
+      vrrp_index = ntohl (mp->vrrp_index);
+      rv = vrrp_vr_update (&vrrp_index, &vr_conf);
+    }
+
+  vec_free (addrs);
+
+  BAD_SW_IF_INDEX_LABEL;
+  // clang-format off
+  REPLY_MACRO2 (VL_API_VRRP_VR_UPDATE_REPLY,
+  ({
+    rmp->vrrp_index = htonl (vrrp_index);
+  }));
+  // clang-format on
+}
+
+static void
+vl_api_vrrp_vr_del_t_handler (vl_api_vrrp_vr_del_t *mp)
+{
+  vl_api_vrrp_vr_del_reply_t *rmp;
+  int rv;
+
+  rv = vrrp_vr_del (ntohl (mp->vrrp_index));
+
+  REPLY_MACRO (VL_API_VRRP_VR_DEL_REPLY);
+}
+
 static void
 vl_api_vrrp_vr_add_del_t_handler (vl_api_vrrp_vr_add_del_t * mp)
 {
-  vrrp_main_t *vmp = &vrrp_main;
   vl_api_vrrp_vr_add_del_reply_t *rmp;
   vrrp_vr_config_t vr_conf;
   u32 api_flags;
   ip46_address_t *addrs = 0;
   int rv;
 
+  VALIDATE_SW_IF_INDEX (mp);
+
   api_flags = htonl (mp->flags);
 
   clib_memset (&vr_conf, 0, sizeof (vr_conf));
@@ -102,13 +206,27 @@ vl_api_vrrp_vr_add_del_t_handler (vl_api_vrrp_vr_add_del_t * mp)
       rv = VNET_API_ERROR_INVALID_VALUE;
     }
   else
-    rv = vrrp_vr_add_del (mp->is_add, &vr_conf);
+    rv = vrrp_vr_add_del (mp->is_add, &vr_conf, NULL);
 
   vec_free (addrs);
 
+  BAD_SW_IF_INDEX_LABEL;
   REPLY_MACRO (VL_API_VRRP_VR_ADD_DEL_REPLY);
 }
 
+static vl_api_vrrp_vr_state_t
+vrrp_vr_state_encode (vrrp_vr_state_t vr_state)
+{
+  if (vr_state == VRRP_VR_STATE_BACKUP)
+    return VRRP_API_VR_STATE_BACKUP;
+  if (vr_state == VRRP_VR_STATE_MASTER)
+    return VRRP_API_VR_STATE_MASTER;
+  if (vr_state == VRRP_VR_STATE_INTF_DOWN)
+    return VRRP_API_VR_STATE_INTF_DOWN;
+
+  return VRRP_API_VR_STATE_INIT;
+}
+
 static void
 send_vrrp_vr_details (vrrp_vr_t * vr, vl_api_registration_t * reg,
                      u32 context)
@@ -147,23 +265,7 @@ send_vrrp_vr_details (vrrp_vr_t * vr, vl_api_registration_t * reg,
   mp->config.flags = htonl (api_flags);
 
   /* runtime */
-  switch (vr->runtime.state)
-    {
-    case VRRP_VR_STATE_INIT:
-      mp->runtime.state = htonl (VRRP_API_VR_STATE_INIT);
-      break;
-    case VRRP_VR_STATE_BACKUP:
-      mp->runtime.state = htonl (VRRP_API_VR_STATE_BACKUP);
-      break;
-    case VRRP_VR_STATE_MASTER:
-      mp->runtime.state = htonl (VRRP_API_VR_STATE_MASTER);
-      break;
-    case VRRP_VR_STATE_INTF_DOWN:
-      mp->runtime.state = htonl (VRRP_API_VR_STATE_INTF_DOWN);
-      break;
-    default:
-      break;
-    }
+  mp->runtime.state = htonl (vrrp_vr_state_encode (vr->runtime.state));
 
   mp->runtime.master_adv_int = htons (vr->runtime.master_adv_int);
   mp->runtime.skew = htons (vr->runtime.skew);
@@ -183,14 +285,14 @@ send_vrrp_vr_details (vrrp_vr_t * vr, vl_api_registration_t * reg,
 
     if (vrrp_vr_is_ipv6 (vr))
       {
-       api_addr->af = htonl (ADDRESS_IP6);
+       api_addr->af = ADDRESS_IP6;
        dst = &api_addr->un.ip6;
        src = &addr->ip6;
        len = sizeof (addr->ip6);
       }
     else
       {
-       api_addr->af = htonl (ADDRESS_IP4);
+       api_addr->af = ADDRESS_IP4;
        dst = &api_addr->un.ip4;
        src = &addr->ip4;
        len = sizeof (addr->ip4);
@@ -211,25 +313,24 @@ vl_api_vrrp_vr_dump_t_handler (vl_api_vrrp_vr_dump_t * mp)
   u32 sw_if_index;
 
   reg = vl_api_client_index_to_registration (mp->client_index);
+  if (!reg)
+    return;
 
   sw_if_index = htonl (mp->sw_if_index);
 
-  /* *INDENT-OFF* */
-  pool_foreach (vr, vmp->vrs, ({
+  pool_foreach (vr, vmp->vrs)  {
 
     if (sw_if_index && (sw_if_index != ~0) &&
        (sw_if_index != vr->config.sw_if_index))
       continue;
 
     send_vrrp_vr_details (vr, reg, mp->context);
-  }));
-  /* *INDENT-ON* */
+  }
 }
 
 static void
 vl_api_vrrp_vr_start_stop_t_handler (vl_api_vrrp_vr_start_stop_t * mp)
 {
-  vrrp_main_t *vmp = &vrrp_main;
   vl_api_vrrp_vr_start_stop_reply_t *rmp;
   vrrp_vr_key_t vr_key;
   int rv;
@@ -248,7 +349,6 @@ vl_api_vrrp_vr_start_stop_t_handler (vl_api_vrrp_vr_start_stop_t * mp)
 static void
 vl_api_vrrp_vr_set_peers_t_handler (vl_api_vrrp_vr_set_peers_t * mp)
 {
-  vrrp_main_t *vmp = &vrrp_main;
   vl_api_vrrp_vr_set_peers_reply_t *rmp;
   vrrp_vr_key_t vr_key;
   ip46_address_t *peer_addrs = 0;
@@ -312,14 +412,14 @@ send_vrrp_vr_peer_details (vrrp_vr_t * vr, vl_api_registration_t * reg,
 
     if (vrrp_vr_is_ipv6 (vr))
       {
-       api_addr->af = htonl (ADDRESS_IP6);
+       api_addr->af = ADDRESS_IP6;
        dst = &api_addr->un.ip6;
        src = &addr->ip6;
        len = sizeof (addr->ip6);
       }
     else
       {
-       api_addr->af = htonl (ADDRESS_IP4);
+       api_addr->af = ADDRESS_IP4;
        dst = &api_addr->un.ip4;
        src = &addr->ip4;
        len = sizeof (addr->ip4);
@@ -340,6 +440,8 @@ vl_api_vrrp_vr_peer_dump_t_handler (vl_api_vrrp_vr_peer_dump_t * mp)
   vrrp_vr_key_t vr_key;
 
   reg = vl_api_client_index_to_registration (mp->client_index);
+  if (!reg)
+    return;
 
   vr_key.sw_if_index = ntohl (mp->sw_if_index);
 
@@ -362,23 +464,20 @@ vl_api_vrrp_vr_peer_dump_t_handler (vl_api_vrrp_vr_peer_dump_t * mp)
       return;
     }
 
-  /* *INDENT-OFF* */
-  pool_foreach (vr, vmp->vrs, ({
+  pool_foreach (vr, vmp->vrs)  {
 
     if (!vec_len (vr->config.peer_addrs))
       continue;
 
     send_vrrp_vr_details (vr, reg, mp->context);
 
-  }));
-  /* *INDENT-ON* */
+  }
 }
 
 static void
   vl_api_vrrp_vr_track_if_add_del_t_handler
   (vl_api_vrrp_vr_track_if_add_del_t * mp)
 {
-  vrrp_main_t *vmp = &vrrp_main;
   vl_api_vrrp_vr_track_if_add_del_reply_t *rmp;
   vrrp_vr_t *vr;
   vrrp_vr_tracking_if_t *track_if, *track_ifs = 0;
@@ -456,6 +555,8 @@ vl_api_vrrp_vr_track_if_dump_t_handler (vl_api_vrrp_vr_track_if_dump_t * mp)
   vrrp_vr_t *vr;
 
   reg = vl_api_client_index_to_registration (mp->client_index);
+  if (!reg)
+    return;
 
   if (!mp->dump_all)
     {
@@ -465,18 +566,57 @@ vl_api_vrrp_vr_track_if_dump_t_handler (vl_api_vrrp_vr_track_if_dump_t * mp)
       return;
     }
 
-  /* *INDENT-OFF* */
-  pool_foreach (vr, vmp->vrs, ({
+  pool_foreach (vr, vmp->vrs)  {
 
     if (!vec_len (vr->tracking.interfaces))
       continue;
 
     send_vrrp_vr_track_if_details (vr, reg, mp->context);
 
-  }));
-  /* *INDENT-ON* */
+  }
+}
+
+static void
+send_vrrp_vr_event (vpe_client_registration_t * reg,
+                   vl_api_registration_t * vl_reg,
+                   vrrp_vr_t * vr, vrrp_vr_state_t new_state)
+{
+  vrrp_main_t *vmp = &vrrp_main;
+  vl_api_vrrp_vr_event_t *mp;
+
+  mp = vl_msg_api_alloc (sizeof (*mp));
+
+  clib_memset (mp, 0, sizeof (*mp));
+  mp->_vl_msg_id = ntohs (VL_API_VRRP_VR_EVENT + vmp->msg_id_base);
+  mp->client_index = reg->client_index;
+  mp->pid = reg->client_pid;
+  mp->vr.sw_if_index = ntohl (vr->config.sw_if_index);
+  mp->vr.vr_id = vr->config.vr_id;
+  mp->vr.is_ipv6 = ((vr->config.flags & VRRP_VR_IPV6) != 0);
+
+  mp->old_state = htonl (vrrp_vr_state_encode (vr->runtime.state));
+  mp->new_state = htonl (vrrp_vr_state_encode (new_state));
+
+  vl_api_send_msg (vl_reg, (u8 *) mp);
+}
+
+void
+vrrp_vr_event (vrrp_vr_t * vr, vrrp_vr_state_t new_state)
+{
+  vpe_api_main_t *vam = &vpe_api_main;
+  vpe_client_registration_t *reg;
+  vl_api_registration_t *vl_reg;
+
+  pool_foreach (reg, vam->vrrp_vr_events_registrations)
+   {
+    vl_reg = vl_api_client_index_to_registration (reg->client_index);
+    if (vl_reg)
+      send_vrrp_vr_event (reg, vl_reg, vr, new_state);
+  }
 }
 
+pub_sub_handler (vrrp_vr_events, VRRP_VR_EVENTS);
+
 /* Set up the API message handling tables */
 #include <vrrp/vrrp.api.c>
 clib_error_t *
@@ -490,7 +630,6 @@ vrrp_plugin_api_hookup (vlib_main_t * vm)
   return 0;
 }
 
-/* *INDENT-ON* */
 
 /*
  * fd.io coding-style-patch-verification: ON