Ack.

Thanks,
Praveen

On 07-Aug-17 1:35 PM, Anders Widell wrote:
A node can have more than one single network address. If you run the ifconfig command, you get a list of network interfaces. Each one of these interfaces can have several address assigned to it: IPv4 addresses, IPv6 addresses, and alias addresses. In addition, the node can have a TIPC address. So in the case of ticket [#2479], we might need to make both saClmNodeAddress and saClmNodeCurrAddress multi-value. However, I don't intend to implement [#2479] in the near future (or at all), since ticket [#2489] is probably enough for most real-world use cases. In most real-world use cases, it is enough for the application to get one single address for each node, but we need the flexibility to select which one of the addresses to present to the application.

saClmNodeAddressFamily and saClmNodeAddress are currently ignored by OpenSAF. I am not sure how saClmNodeAddressFamily and saClmNodeAddress are intended to be used, but my best guess is that saClmNodeAddress is intended for the case when you have statically assigned network addresses, and saClmNodeCurrAddress is intended for the case with dynamically assigned addresses, though there is no reason why we can't present a statically assigned address in saClmNodeCurrAddress as well. Since saClmNodeAddress is a configuration attribute, I am assuming here that you should actually be able to /set/ the node's address using the saClmNodeAddress configuration attribute! But in order for that to work, the node needs to read its IMM configuration immediately after booting, before it has configured its own network address. The only way this could work is if we are not actually talking about the network address used internally by OpenSAF, but the node's address on a separate network intended to be used by the application. Otherwise OpenSAF would not be able to communicate with IMM to read the node's own address. So according to this interpretation, each node has at least two addresses: one address used for internal OpenSAF communication, and another address used by the application. And it is the address used by the application which is configured using the saClmNodeAddress and presented in the saClmNodeCurrAddress attribute. Ticket doesn't favour any particular interpretation though, you are free to select the internal OpenSAF communication address or some other address to present in saClmNodeCurrAddress.

regards,

Anders Widell

On 08/07/2017 07:12 AM, praveen malviya wrote:
Hi Anders,

I have started reviewing this patch.

One initial query:
We have two sets of attributes for address in "SaClmNode":
set A) saClmNodeAddressFamily & saClmNodeAddress  and
set B )saClmNodeCurrAddressFamily & saClmNodeCurrAddress.

For ticket #2479, its description says making set B as Multi valued. I think it is set A that should be made multi-valued and set B should reflect the address currently in use. This will resolve some backward compatibility issue also as set B remains single valued.

Also the set B should reflect which address? address used by OpenSAF or by application? Till this time it has been OpenSAF internal communication address.


Thanks,
Praveen

On 31-Jul-17 6:40 PM, Anders Widell wrote:
The node join request message now has two new fields: boot time and node
address. This allows us to provide more accurate and correct information in the
CLM node runtime attributes in the information model:

* The boot time field transmits the node's actual boot time to the CLM server. Previously, the node join time was used as an approximation of the node boot time, but this might be inaccurate or incorrect. For example, if OpenSAF was started much later than the node was booted (e.g. if OpenSAF was restarted without a node reboot), then the node join time will differ significantly from
   the node boot time.

* The node address field transmits the node address to be presented to the application through the information model. Previously, the IP address which was used by OpenSAF internal communication was presented as the one and only node address, and there was no way to select some other address in case the node has multiple network addresses. The application now has the possibility
   to select which network address to present in the information model.
---
  00-README.conf                 |  8 ++++
  src/clm/clmd/clms.h            |  1 -
  src/clm/clmd/clms_evt.c        | 15 ++++++-
  src/clm/clmd/clms_main.c       | 22 ++++++----
  src/clm/clmd/clms_mbcsv.c      | 11 ++---
  src/clm/clmd/clms_mbcsv.h      |  2 -
src/clm/clmd/clms_mds.c | 92 +++++++++++++++++++++++++-----------------
  src/clm/clmd/clms_util.c       | 15 -------
  src/clm/clmnd/cb.h             | 14 ++++---
  src/clm/clmnd/clmna.conf       | 13 ++++++
src/clm/clmnd/main.c | 89 ++++++++++++++++++++++++++++++++--------
  src/clm/common/clmsv_enc_dec.c | 34 +++++++++++++++-
  src/clm/common/clmsv_enc_dec.h |  2 +
  src/clm/common/clmsv_msg.h     |  5 +++
  14 files changed, 232 insertions(+), 91 deletions(-)

diff --git a/00-README.conf b/00-README.conf
index 380cdc2f4..b99999ef1 100644
--- a/00-README.conf
+++ b/00-README.conf
@@ -65,6 +65,14 @@ controller nodes, the default delay of 200 ms should be sufficient. For systems with a very large number of configured system controller nodes and/or with
  unreliable network connections, values larger than 5000 may be needed.
+CLMNA_ADDR_FAMILY and CLMNA_ADDR_VALUE let you specify the values shown in the +saClmNodeCurrAddressFamily and saClmNodeCurrAddress runtime attributes of the +node's SaClmNode IMM object. If these options are not set, CLM will try to try +to figure out the node's address by itself. Since a node can have more than one
+network address, the address chosen by CLM may not be the address your
+application is interested in. By explicitly specifying the address using +CLMNA_ADDR_FAMILY and CLMNA_ADDR_VALUE, you will be guaranteed that the correct
+address is presented.
*******************************************************************************
  dtmd.conf
diff --git a/src/clm/clmd/clms.h b/src/clm/clmd/clms.h
index 664c0da29..2ac69eade 100644
--- a/src/clm/clmd/clms.h
+++ b/src/clm/clmd/clms.h
@@ -116,7 +116,6 @@ extern SaAisErrorT clms_plm_init(CLMS_CB *cb);
  #endif
  extern void clms_node_add_to_model(CLMS_CLUSTER_NODE *node);
  extern SaTimeT clms_get_SaTime(void);
-extern SaTimeT clms_get_BootTime(void);
  extern void clms_imm_impl_set(CLMS_CB *cb);
  extern uint32_t clms_rda_init(CLMS_CB *cb);
  extern void clms_adminop_pending(void);
diff --git a/src/clm/clmd/clms_evt.c b/src/clm/clmd/clms_evt.c
index d29925b77..ace140db4 100644
--- a/src/clm/clmd/clms_evt.c
+++ b/src/clm/clmd/clms_evt.c
@@ -1,6 +1,7 @@
  /*      -*- OpenSAF  -*-
   *
   * (C) Copyright 2010,2015 The OpenSAF Foundation
+ * Copyright Ericsson AB 2017 - All Rights Reserved.
   *
   * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY @@ -664,11 +665,12 @@ uint32_t proc_node_up_msg(CLMS_CB *cb, CLMSV_CLMS_EVT *evt)
                  "/node_name configuration");
          }
      }
-    node->boot_time = clms_get_SaTime();
+    node->boot_time =
+ evt->info.msg.info.api_info.param.nodeup_info.boot_time;
        /* Update the node with ipaddress information */
      if (ip->addr.length) {
-        memset(&node->node_addr, 0 , sizeof(SaClmNodeAddressT));
+        memset(&node->node_addr, 0, sizeof(SaClmNodeAddressT));
          node->node_addr.family = ip->addr.family;
          node->node_addr.length = ip->addr.length;
memcpy(node->node_addr.value, ip->addr.value, ip->addr.length); @@ -677,6 +679,15 @@ uint32_t proc_node_up_msg(CLMS_CB *cb, CLMSV_CLMS_EVT *evt)
          node->node_addr.length = 0;
      }
+ // If the node has sent us its address, this takes precedence over the
+    // address given by MDS.
+ if (evt->info.msg.info.api_info.param.nodeup_info.no_of_addresses !=
+        0) {
+        SaClmNodeAddressT *node_addr =
+ &(evt->info.msg.info.api_info.param.nodeup_info.address);
+        memcpy(&(node->node_addr), node_addr, sizeof(*node_addr));
+    }
+
/*When plm not in model,membership status depends only on the nodeup */
      if (node->admin_state == SA_CLM_ADMIN_UNLOCKED) {
  diff --git a/src/clm/clmd/clms_main.c b/src/clm/clmd/clms_main.c
index c21e89bab..0b84aeab9 100644
--- a/src/clm/clmd/clms_main.c
+++ b/src/clm/clmd/clms_main.c
@@ -1,6 +1,7 @@
  /*      -*- OpenSAF  -*-
   *
   * (C) Copyright 2008,2015 The OpenSAF Foundation
+ * Copyright Ericsson AB 2017 - All Rights Reserved.
   *
   * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
@@ -21,18 +22,17 @@
* ========================================================================
   */
  -#include <string.h>
+#include <poll.h>
+#include <signal.h>
  #include <stdio.h>
  #include <stdlib.h>
+#include <string.h>
  #include <time.h>
-#include <signal.h>
-#include <poll.h>
-
-#include "osaf/configmake.h"
  #include "base/daemon.h"
-
+#include "base/osaf_time.h"
+#include "clm/clmd/clms.h"
  #include "nid/agent/nid_api.h"
-#include "clms.h"
+#include "osaf/configmake.h"
  #include "osaf/saflog/saflog.h"
/* ========================================================================
@@ -184,7 +184,13 @@ static uint32_t clms_self_node_info(void)
      if (node->admin_state == SA_CLM_ADMIN_UNLOCKED) {
          node->member = SA_TRUE;
          ++(osaf_cluster->num_nodes);
-        node->boot_time = clms_get_BootTime();
+        struct timespec boot_time;
+        osaf_get_boot_time(&boot_time);
+ // Round boot time to 10 microseconds, so that multiple readings
+        // are likely to result in the same value.
+        uint64_t boot_time_10us =
+            (osaf_timespec_to_nanos(&boot_time) + 5000) / 10000;
+        node->boot_time = boot_time_10us * 10000;
  #ifdef ENABLE_AIS_PLM
          node->ee_red_state =
              SA_PLM_READINESS_IN_SERVICE; /*TBD : changed when plm
diff --git a/src/clm/clmd/clms_mbcsv.c b/src/clm/clmd/clms_mbcsv.c
index fa951276a..47e449417 100644
--- a/src/clm/clmd/clms_mbcsv.c
+++ b/src/clm/clmd/clms_mbcsv.c
@@ -17,9 +17,10 @@
   */
    #include "base/ncsencdec_pub.h"
-#include "clms.h"
-#include "clms_mbcsv.h"
-#include "clms_evt.h"
+#include "clm/clmd/clms.h"
+#include "clm/clmd/clms_evt.h"
+#include "clm/clmd/clms_mbcsv.h"
+#include "clm/common/clmsv_enc_dec.h"
static uint32_t ckpt_proc_cluster_rec(CLMS_CB *cb, CLMS_CKPT_REC *data);
  static uint32_t ckpt_proc_reg_rec(CLMS_CB *cb, CLMS_CKPT_REC *data);
@@ -1829,7 +1830,7 @@ uint32_t enc_mbcsv_node_config_msg(NCS_UBAID *uba,
      /** encode the contents **/
      total_bytes += clmsv_encodeSaNameT(uba, &param->node_name);
      total_bytes += clmsv_encodeSaNameT(uba, &param->ee_name);
-    total_bytes += encodeNodeAddressT(uba, &param->node_addr);
+    total_bytes += clmsv_encodeNodeAddressT(uba, &param->node_addr);
        p8 = ncs_enc_reserve_space(uba, 4);
      if (!p8) {
@@ -1886,7 +1887,7 @@ uint32_t enc_mbcsv_node_msg(NCS_UBAID *uba, CLMSV_CKPT_NODE *param)
      ncs_enc_claim_space(uba, 4);
      total_bytes += 4;
  -    total_bytes += encodeNodeAddressT(uba, &param->node_addr);
+    total_bytes += clmsv_encodeNodeAddressT(uba, &param->node_addr);
      total_bytes += clmsv_encodeSaNameT(uba, &param->node_name);
      total_bytes += clmsv_encodeSaNameT(uba, &param->ee_name);
  diff --git a/src/clm/clmd/clms_mbcsv.h b/src/clm/clmd/clms_mbcsv.h
index f744e4c15..ae429fda2 100644
--- a/src/clm/clmd/clms_mbcsv.h
+++ b/src/clm/clmd/clms_mbcsv.h
@@ -172,8 +172,6 @@ extern void prepare_ckpt_to_ckpt_node(CLMSV_CKPT_NODE *node,
                                        CLMSV_CKPT_NODE *cluster_node);
  extern void prepare_ckpt_to_ckpt_config_node(
CLMSV_CKPT_NODE_CONFIG_REC *node, CLMSV_CKPT_NODE_CONFIG_REC *cluster_node);
-extern uint32_t encodeNodeAddressT(NCS_UBAID *uba,
-                                   SaClmNodeAddressT *nodeAddress);
extern void send_async_update_for_node_rec(CLMS_CLUSTER_NODE *cluster_node);
  #endif  // CLM_CLMD_CLMS_MBCSV_H_
diff --git a/src/clm/clmd/clms_mds.c b/src/clm/clmd/clms_mds.c
index 99c195d90..1eb0e1e62 100644
--- a/src/clm/clmd/clms_mds.c
+++ b/src/clm/clmd/clms_mds.c
@@ -1,6 +1,7 @@
  /*      -*- OpenSAF  -*-
   *
   * (C) Copyright 2008 The OpenSAF Foundation
+ * Copyright Ericsson AB 2017 - All Rights Reserved.
   *
   * This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
@@ -15,8 +16,12 @@
   *
   */
  +#include <inttypes.h>
+#include <string.h>
+#include "base/logtrace.h"
  #include "base/ncsencdec_pub.h"
-#include "clms.h"
+#include "clm/clmd/clms.h"
+#include "clm/common/clmsv_enc_dec.h"
    #define CLMS_SVC_PVT_SUBPART_VERSION 1
  #define CLMS_WRT_CLMA_SUBPART_VER_AT_MIN_MSG_FMT 1
@@ -286,37 +291,6 @@ done:
      return total_bytes;
  }
-uint32_t encodeNodeAddressT(NCS_UBAID *uba, SaClmNodeAddressT *nodeAddress)
-{
-    uint8_t *p8 = NULL;
-    uint32_t total_bytes = 0;
-
-    p8 = ncs_enc_reserve_space(uba, 4);
-    if (!p8) {
-        TRACE("p8 NULL!!!");
-        return 0;
-    }
-    ncs_encode_32bit(&p8, nodeAddress->family);
-    ncs_enc_claim_space(uba, 4);
-    total_bytes += 4;
-    p8 = ncs_enc_reserve_space(uba, 2);
-    if (!p8) {
-        TRACE("p8 NULL!!!");
-        return 0;
-    }
-    if (nodeAddress->length > SA_CLM_MAX_ADDRESS_LENGTH) {
-        LOG_ER("SaNameT length too long %hd", nodeAddress->length);
-        osafassert(0);
-    }
-    ncs_encode_16bit(&p8, nodeAddress->length);
-    ncs_enc_claim_space(uba, 2);
-    total_bytes += 2;
-    ncs_encode_n_octets_in_uba(uba, nodeAddress->value,
-                   (uint32_t)nodeAddress->length);
-    total_bytes += (uint32_t)nodeAddress->length;
-    return total_bytes;
-}
-
static uint32_t clms_enc_node_get_msg(NCS_UBAID *uba, SaClmClusterNodeT_4 *msg)
  {
      uint8_t *p8;
@@ -332,7 +306,7 @@ static uint32_t clms_enc_node_get_msg(NCS_UBAID *uba, SaClmClusterNodeT_4 *msg)
      ncs_enc_claim_space(uba, 4);
      total_bytes += 4;
  -    total_bytes += encodeNodeAddressT(uba, &param->nodeAddress);
+    total_bytes += clmsv_encodeNodeAddressT(uba, &param->nodeAddress);
      total_bytes += clmsv_encodeSaNameT(uba, &param->nodeName);
total_bytes += clmsv_encodeSaNameT(uba, &param->executionEnvironment);
  @@ -783,6 +757,17 @@ err:
      return NCSCC_RC_FAILURE;
  }
  +static void trace_node_address(const SaClmNodeAddressT *node_addr)
+{
+    char addr[SA_CLM_MAX_ADDRESS_LENGTH + 1];
+    size_t len = node_addr->length;
+    if (len > SA_CLM_MAX_ADDRESS_LENGTH)
+        len = SA_CLM_MAX_ADDRESS_LENGTH;
+    memcpy(addr, node_addr->value, len);
+    addr[len] = '\0';
+ TRACE("Address family %d, value '%s'", (int)node_addr->family, addr);
+}
+
  /**
   * Decode the nodeup msg
   **/
@@ -790,7 +775,7 @@ static uint32_t clms_dec_nodeup_msg(NCS_UBAID *uba, CLMSV_MSG *msg)
  {
      uint8_t *p8;
      uint32_t total_bytes = 0;
-    uint8_t local_data[4];
+    uint8_t local_data[8];
      TRACE_ENTER();
        p8 = ncs_dec_flatten_space(uba, local_data, 4);
@@ -802,7 +787,42 @@ static uint32_t clms_dec_nodeup_msg(NCS_UBAID *uba, CLMSV_MSG *msg)
      TRACE("nodename %s length %d",
msg->info.api_info.param.nodeup_info.node_name.value,
msg->info.api_info.param.nodeup_info.node_name.length);
-
+    p8 = ncs_dec_flatten_space(uba, local_data, 8);
+ // Old protocol versions don't have the boot_time field. Use the current
+    // wall clock time if boot_time isn't present in the message.
+    uint64_t boot_time;
+    if (p8 != NULL) {
+        boot_time = ncs_decode_64bit(&p8);
+        ncs_dec_skip_space(uba, 8);
+        total_bytes += 8;
+        TRACE("Boot time: %" PRIu64, boot_time);
+    } else {
+        boot_time = clms_get_SaTime();
+    }
+    msg->info.api_info.param.nodeup_info.boot_time = boot_time;
+    p8 = ncs_dec_flatten_space(uba, local_data, 2);
+ // Old protocol versions don't have the no_of_addresses field, and hence + // no addresses in the message. Just stop decoding if no_of_addresses
+    // isn't found.
+    uint16_t no_of_addresses = 0;
+    if (p8 != NULL) {
+        no_of_addresses = ncs_decode_16bit(&p8);
+        ncs_dec_skip_space(uba, 2);
+        total_bytes += 2;
+        TRACE("Number of node addresses: %" PRIu16, no_of_addresses);
+    }
+ msg->info.api_info.param.nodeup_info.no_of_addresses = no_of_addresses;
+    SaClmNodeAddressT *node_addr =
+        &(msg->info.api_info.param.nodeup_info.address);
+    if (no_of_addresses != 0) {
+        total_bytes += clmsv_decodeNodeAddressT(uba, node_addr);
+        trace_node_address(node_addr);
+    }
+    // For now we only use the first address, skip the rest.
+    for (uint16_t i = 1; i < no_of_addresses; ++i) {
+        SaClmNodeAddressT nodeAddress;
+        total_bytes += clmsv_decodeNodeAddressT(uba, &nodeAddress);
+    }
      TRACE("CLMSV_NODE_UP_MSG");
      TRACE_LEAVE();
      return total_bytes;
@@ -1637,4 +1657,4 @@ uint32_t clms_mds_msg_bcast(CLMS_CB *cb, CLMSV_MSG *bcast_msg)
      }
        return NCSCC_RC_SUCCESS;
-}
\ No newline at end of file
+}
diff --git a/src/clm/clmd/clms_util.c b/src/clm/clmd/clms_util.c
index f150606d8..be3052867 100644
--- a/src/clm/clmd/clms_util.c
+++ b/src/clm/clmd/clms_util.c
@@ -308,21 +308,6 @@ SaTimeT clms_get_SaTime(void)
      return osaf_timespec_to_nanos(&realtime);
  }
  -SaTimeT clms_get_BootTime(void)
-{
-    struct timespec monotonic;
-    struct timespec realtime;
-    struct timespec boottime;
-    osaf_clock_gettime(CLOCK_MONOTONIC, &monotonic);
-    osaf_clock_gettime(CLOCK_REALTIME, &realtime);
-    if (osaf_timespec_compare(&realtime, &monotonic) >= 0) {
-        osaf_timespec_subtract(&realtime, &monotonic, &boottime);
-    } else {
-        boottime = realtime;
-    }
-    return osaf_timespec_to_nanos(&boottime);
-}
-
  /**
   * Validate the saClmNode DN
   * @param[in] DN
diff --git a/src/clm/clmnd/cb.h b/src/clm/clmnd/cb.h
index 1723883dd..9b26a9bf5 100644
--- a/src/clm/clmnd/cb.h
+++ b/src/clm/clmnd/cb.h
@@ -20,22 +20,26 @@
  #define CLM_CLMND_CB_H_
    #include <assert.h>
-#include <stdlib.h>
+#include <poll.h>
+#include <saClm.h>
  #include <stdbool.h>
+#include <stdlib.h>
  #include <string.h>
-#include <poll.h>
  #include <unistd.h>
-#include "osaf/configmake.h"
  #include "base/daemon.h"
-#include "nid/agent/nid_api.h"
-#include "mds/mds_papi.h"
  #include "base/ncssysf_ipc.h"
  #include "base/ncssysf_tmr.h"
+#include "mds/mds_papi.h"
+#include "nid/agent/nid_api.h"
+#include "osaf/configmake.h"
    /* Self node information */
  typedef struct node_detail_t {
    SaUint32T node_id;
    SaNameT node_name;
+  SaTimeT boot_time;
+  SaUint16T no_of_addresses;
+  SaClmNodeAddressT address;
  } NODE_INFO;
    /* CLM Server control block */
diff --git a/src/clm/clmnd/clmna.conf b/src/clm/clmnd/clmna.conf
index ed9efdebb..18a5a1b5a 100644
--- a/src/clm/clmnd/clmna.conf
+++ b/src/clm/clmnd/clmna.conf
@@ -18,5 +18,18 @@ export CLMNA_ENV_HEALTHCHECK_KEY="Default"
  # with more than two system controllers.
  #export CLMNA_ELECTION_DELAY_TIME=200
+# Uncomment the next two lines to specify the address that will be presented to
+# the application through the information model. CLMNA_ADDR_FAMILY and
+# CLMNA_ADDR_VALUE let you specify the values shown in the
+# saClmNodeCurrAddressFamily and saClmNodeCurrAddress runtime attributes of the +# node's SaClmNode IMM object. If these options are not set, CLM will try to try +# to figure out the node's address by itself. Since a node can have more than +# one network address, the address chosen by CLM may not be the address your +# application is interested in. By explicitly specifying the address using +# CLMNA_ADDR_FAMILY and CLMNA_ADDR_VALUE, you will be guaranteed that the
+# correct address is presented.
+#export CLMNA_ADDR_FAMILY=1
+#export CLMNA_ADDR_VALUE=10.130.100.114
+
  # Uncomment the next line to enable info level logging
  #args="--loglevel=info"
diff --git a/src/clm/clmnd/main.c b/src/clm/clmnd/main.c
index 4956ba668..3a8479600 100644
--- a/src/clm/clmnd/main.c
+++ b/src/clm/clmnd/main.c
@@ -18,28 +18,28 @@
    #include <errno.h>
  #include <inttypes.h>
+#include <saClm.h>
+#include <stdbool.h>
  #include <stdint.h>
  #include <stdlib.h>
  #include <string.h>
-#include <stdbool.h>
-#include "clm/clmnd/cb.h"
-#include "base/ncs_main_papi.h"
+#include "base/logtrace.h"
  #include "base/ncs_hdl_pub.h"
-#include "base/ncsencdec_pub.h"
+#include "base/ncs_main_papi.h"
  #include "base/ncs_mda_pvt.h"
  #include "base/ncs_util.h"
-#include "base/logtrace.h"
-#include <saClm.h>
-#include "osaf/configmake.h"
-#include "clm/common/clmsv_msg.h"
-#include "clm/common/clmsv_enc_dec.h"
-#include "clm/clmnd/evt.h"
-#include "clmna.h"
+#include "base/ncsencdec_pub.h"
+#include "base/ncsgl_defs.h"
  #include "base/osaf_poll.h"
  #include "base/osaf_time.h"
-#include "base/ncsgl_defs.h"
+#include "clm/clmnd/cb.h"
+#include "clm/clmnd/clmna.h"
+#include "clm/clmnd/election_starter_wrapper.h"
+#include "clm/clmnd/evt.h"
+#include "clm/common/clmsv_enc_dec.h"
+#include "clm/common/clmsv_msg.h"
  #include "mds/mds_papi.h"
-#include "election_starter_wrapper.h"
+#include "osaf/configmake.h"
    enum { FD_TERM = 0, FD_AMF, FD_MBX, NUM_FD };
@@ -389,6 +389,28 @@ static uint32_t clmna_mds_enc(struct ncsmds_callback_info *info)
              total_bytes += clmsv_encodeSaNameT(
                  uba,
&(msg->info.api_info.param.nodeup_info.node_name));
+            p8 = ncs_enc_reserve_space(uba, 8);
+            ncs_encode_64bit(
+                &p8,
+ msg->info.api_info.param.nodeup_info.boot_time);
+            ncs_enc_claim_space(uba, 8);
+            total_bytes += 8;
+            TRACE("Encoded boot time: %" PRIu64,
+ (uint64_t)msg->info.api_info.param.nodeup_info
+                  .boot_time);
+            uint16_t no_of_addresses =
+                msg->info.api_info.param.nodeup_info
+                .no_of_addresses;
+            p8 = ncs_enc_reserve_space(uba, 2);
+            ncs_encode_16bit(&p8, no_of_addresses);
+            ncs_enc_claim_space(uba, 2);
+            total_bytes += 2;
+            if (no_of_addresses != 0) {
+                osafassert(no_of_addresses == 1);
+                total_bytes += clmsv_encodeNodeAddressT(
+                    uba, &(msg->info.api_info.param.nodeup_info
+                           .address));
+            }
          }
      }
  @@ -504,7 +526,7 @@ static int get_node_info(NODE_INFO *node)
      }
      fclose(fp);
      node->node_name.length = strlen((char *)node->node_name.value);
-    TRACE("%s", node->node_name.value);
+    TRACE("node name: '%s'", node->node_name.value);
        fp = fopen(PKGLOCALSTATEDIR "/node_id", "r");
      if (fp == NULL) {
@@ -519,8 +541,38 @@ static int get_node_info(NODE_INFO *node)
          return -1;
      }
      fclose(fp);
-    TRACE("%d", node->node_id);
-
+    TRACE("node id: 0x%" PRIx32, node->node_id);
+    struct timespec boot_time;
+    osaf_get_boot_time(&boot_time);
+ // Round boot time to 10 microseconds, so that multiple readings are
+    // likely to result in the same value.
+    uint64_t boot_time_10us =
+        (osaf_timespec_to_nanos(&boot_time) + 5000) / 10000;
+    node->boot_time = boot_time_10us * 10000;
+    TRACE("Boot time: %" PRIu64, (uint64_t)node->boot_time);
+
+    long family_val = 0;
+    char *family = getenv("CLMNA_ADDR_FAMILY");
+    char *value = getenv("CLMNA_ADDR_VALUE");
+    if (family != NULL) {
+        char *endptr = family;
+        errno = 0;
+        family_val = strtol(family, &endptr, 0);
+        if (errno != 0 || *endptr != '\0' || *family == '\0')
+            family = NULL;
+    }
+    if (family != NULL && value != NULL) {
+        size_t len = strlen(value);
+        if (len > SA_CLM_MAX_ADDRESS_LENGTH)
+            len = SA_CLM_MAX_ADDRESS_LENGTH;
+        node->address.family = family_val;
+        node->address.length = len;
+        memcpy(node->address.value, value, len);
+        node->no_of_addresses = 1;
+    } else {
+        node->no_of_addresses = 0;
+        memset(&node->address, 0, sizeof(node->address));
+    }
      return 0;
  }
  @@ -621,6 +673,11 @@ static void clmna_process_dummyup_msg(void)
msg.info.api_info.param.nodeup_info.node_id = self_node.node_id;
          msg.info.api_info.param.nodeup_info.node_name =
              self_node.node_name;
+        msg.info.api_info.param.nodeup_info.boot_time =
+            self_node.boot_time;
+        msg.info.api_info.param.nodeup_info.no_of_addresses =
+            self_node.no_of_addresses;
+ msg.info.api_info.param.nodeup_info.address = self_node.address;
          stop_scale_out_retry_tmr();
          start_scale_out_retry_tmr(CLMNA_JOIN_RETRY_TIME);
          uint32_t rc = clmna_mds_msg_send(&msg);
diff --git a/src/clm/common/clmsv_enc_dec.c b/src/clm/common/clmsv_enc_dec.c
index 8d37e79be..e4688984c 100644
--- a/src/clm/common/clmsv_enc_dec.c
+++ b/src/clm/common/clmsv_enc_dec.c
@@ -62,7 +62,7 @@ uint32_t clmsv_decodeNodeAddressT(NCS_UBAID *uba,
        p8 = ncs_dec_flatten_space(uba, local_data, 2);
      nodeAddress->length = ncs_decode_16bit(&p8);
-    if (nodeAddress->length > SA_MAX_NAME_LENGTH) {
+    if (nodeAddress->length > SA_CLM_MAX_ADDRESS_LENGTH) {
          LOG_ER("nodeAddress->length length too long: %hd",
                 nodeAddress->length);
          /* this should not happen */
@@ -103,3 +103,35 @@ uint32_t clmsv_encodeSaNameT(NCS_UBAID *uba, SaNameT *name)
      TRACE_LEAVE();
      return total_bytes;
  }
+
+uint32_t clmsv_encodeNodeAddressT(NCS_UBAID *uba,
+                  SaClmNodeAddressT *nodeAddress)
+{
+    uint8_t *p8 = NULL;
+    uint32_t total_bytes = 0;
+
+    p8 = ncs_enc_reserve_space(uba, 4);
+    if (!p8) {
+        TRACE("p8 NULL!!!");
+        return 0;
+    }
+    ncs_encode_32bit(&p8, nodeAddress->family);
+    ncs_enc_claim_space(uba, 4);
+    total_bytes += 4;
+    p8 = ncs_enc_reserve_space(uba, 2);
+    if (!p8) {
+        TRACE("p8 NULL!!!");
+        return 0;
+    }
+    if (nodeAddress->length > SA_CLM_MAX_ADDRESS_LENGTH) {
+        LOG_ER("SaNameT length too long %hd", nodeAddress->length);
+        osafassert(0);
+    }
+    ncs_encode_16bit(&p8, nodeAddress->length);
+    ncs_enc_claim_space(uba, 2);
+    total_bytes += 2;
+    ncs_encode_n_octets_in_uba(uba, nodeAddress->value,
+                   (uint32_t)nodeAddress->length);
+    total_bytes += (uint32_t)nodeAddress->length;
+    return total_bytes;
+}
diff --git a/src/clm/common/clmsv_enc_dec.h b/src/clm/common/clmsv_enc_dec.h
index e676e3b07..5fa94c07f 100644
--- a/src/clm/common/clmsv_enc_dec.h
+++ b/src/clm/common/clmsv_enc_dec.h
@@ -32,5 +32,7 @@ uint32_t clmsv_decodeSaNameT(NCS_UBAID *uba, SaNameT *name);
  uint32_t clmsv_decodeNodeAddressT(NCS_UBAID *uba,
                                    SaClmNodeAddressT *nodeAddress);
  uint32_t clmsv_encodeSaNameT(NCS_UBAID *uba, SaNameT *name);
+uint32_t clmsv_encodeNodeAddressT(NCS_UBAID *uba,
+                                  SaClmNodeAddressT *nodeAddress);
    #endif  // CLM_COMMON_CLMSV_ENC_DEC_H_
diff --git a/src/clm/common/clmsv_msg.h b/src/clm/common/clmsv_msg.h
index 2df0730ee..f312659f7 100644
--- a/src/clm/common/clmsv_msg.h
+++ b/src/clm/common/clmsv_msg.h
@@ -17,6 +17,8 @@
  #ifndef CLM_COMMON_CLMSV_MSG_H_
  #define CLM_COMMON_CLMSV_MSG_H_
  +#include <saClm.h>
+
  /* CLMS->CLMA && CLMA->CLMS message types */
  typedef enum clms_msg_type {
    CLMSV_CLMA_TO_CLMS_API_MSG = 0,
@@ -137,6 +139,9 @@ typedef struct clmsv_track_info_t {
  typedef struct {
    SaUint32T node_id;
    SaNameT node_name;
+  SaTimeT boot_time;
+  SaUint16T no_of_addresses;
+  SaClmNodeAddressT address;
  } clmsv_clms_node_up_info_t;
    typedef struct clmsv_api_info_t {



------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Opensaf-devel mailing list
Opensaf-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to