qdevice-net-algo-test.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. /*
  2. * Copyright (c) 2015-2016 Red Hat, Inc.
  3. *
  4. * All rights reserved.
  5. *
  6. * Author: Jan Friesse (jfriesse@redhat.com)
  7. *
  8. * This software licensed under BSD license, the text of which follows:
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions are met:
  12. *
  13. * - Redistributions of source code must retain the above copyright notice,
  14. * this list of conditions and the following disclaimer.
  15. * - Redistributions in binary form must reproduce the above copyright notice,
  16. * this list of conditions and the following disclaimer in the documentation
  17. * and/or other materials provided with the distribution.
  18. * - Neither the name of the Red Hat, Inc. nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  23. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  26. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  27. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  28. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  29. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  30. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  31. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  32. * THE POSSIBILITY OF SUCH DAMAGE.
  33. */
  34. #include <sys/types.h>
  35. #include <string.h>
  36. #include "qdevice-net-algo-test.h"
  37. #include "qdevice-log.h"
  38. #include "qdevice-net-send.h"
  39. #include "qdevice-net-cast-vote-timer.h"
  40. /*
  41. * Called after qdevice_net_instance is initialized. Connection to server is not yet
  42. * established. Used mainly for allocating instance->algorithm_data.
  43. *
  44. * Callback should return 0 on success or -1 on failure.
  45. */
  46. int
  47. qdevice_net_algo_test_init(struct qdevice_net_instance *instance)
  48. {
  49. instance->algorithm_data = NULL;
  50. qdevice_log(LOG_INFO, "algo-test: Initialized");
  51. return (0);
  52. }
  53. /*
  54. * Called after qdevice connected to qnetd.
  55. * send_config_node_list, send_membership_node_list and send_quorum_node_list can be set to
  56. * nonzero (default) to make qdevice-net send given lists to qnetd
  57. * vote (default TLV_VOTE_WAIT_FOR_REPLY) can be set to update voting timer
  58. *
  59. * Callback should return 0 on success or -1 on failure (-> disconnect client).
  60. */
  61. int
  62. qdevice_net_algo_test_connected(struct qdevice_net_instance *instance, int *send_config_node_list,
  63. int *send_membership_node_list, int *send_quorum_node_list, enum tlv_vote *vote)
  64. {
  65. qdevice_log(LOG_INFO, "algo-test: Connected");
  66. return (0);
  67. }
  68. /*
  69. * Called after config node list changed.
  70. *
  71. * Callback can override send_node_list and vote.
  72. * Depending on net_instance->state, they are set acordingly:
  73. * If net_instance->state != QDEVICE_NET_INSTANCE_STATE_WAITING_VOTEQUORUM_CMAP_EVENTS
  74. * send_node_list = 0
  75. * if cast_vote_timer_vote != TLV_VOTE_ACK
  76. * vote = TLV_VOTE_NO_CHANGE
  77. * if cast_vote_timer_vote = TLV_VOTE_ACK
  78. * vote = TLV_VOTE_NACK.
  79. * Otherwise send_node_list = 0 and vote = TLV_VOTE_NO_CHANGE
  80. * If send_node_list is set to non zero, node list is send to qnetd
  81. */
  82. int
  83. qdevice_net_algo_test_config_node_list_changed(struct qdevice_net_instance *instance,
  84. const struct node_list *nlist, int config_version_set, uint64_t config_version,
  85. int *send_node_list, enum tlv_vote *vote)
  86. {
  87. qdevice_log(LOG_INFO, "algo-test: Config node list changed");
  88. return (0);
  89. }
  90. /*
  91. * Called after votequorum node list notify is dispatched.
  92. *
  93. * Callback should return 0 on success or -1 on failure (-> disconnect client).
  94. *
  95. * If net_instance->state != QDEVICE_NET_INSTANCE_STATE_WAITING_VOTEQUORUM_CMAP_EVENTS
  96. * send_node_list = 0
  97. * if cast_vote_timer_vote != TLV_VOTE_ACK
  98. * vote = TLV_VOTE_NO_CHANGE
  99. * if cast_vote_timer_vote = TLV_VOTE_ACK
  100. * vote = TLV_VOTE_NACK.
  101. * Otherwise send_node_list = 0 and vote = TLV_VOTE_NO_CHANGE
  102. * If send_node_list is set to non zero, node list is send to qnetd
  103. */
  104. int
  105. qdevice_net_algo_test_votequorum_node_list_notify(struct qdevice_net_instance *instance,
  106. const struct tlv_ring_id *ring_id, uint32_t node_list_entries, uint32_t node_list[],
  107. int *send_node_list, enum tlv_vote *vote)
  108. {
  109. qdevice_log(LOG_INFO, "algo-test: Votequorum list notify");
  110. return (0);
  111. }
  112. /*
  113. * Called after votequorum quorum notify is dispatched.
  114. *
  115. * Callback should return 0 on success or -1 on failure (-> disconnect client).
  116. *
  117. * Callback can override send_node_list and vote.
  118. * Depending on net_instance->state, they are set acordingly:
  119. * If net_instance->state != QDEVICE_NET_INSTANCE_STATE_WAITING_VOTEQUORUM_CMAP_EVENTS
  120. * send_node_list = 0
  121. * if cast_vote_timer_vote != TLV_VOTE_ACK
  122. * vote = TLV_VOTE_NO_CHANGE
  123. * if cast_vote_timer_vote = TLV_VOTE_ACK
  124. * vote = TLV_VOTE_NACK.
  125. * Otherwise send_node_list = 0 and vote = TLV_VOTE_NO_CHANGE
  126. *
  127. * If send_node_list is set to non zero, node list is send to qnetd
  128. */
  129. int
  130. qdevice_net_algo_test_votequorum_quorum_notify(struct qdevice_net_instance *instance,
  131. uint32_t quorate, uint32_t node_list_entries, votequorum_node_t node_list[], int *send_node_list,
  132. enum tlv_vote *vote)
  133. {
  134. qdevice_log(LOG_INFO, "algo-test: Votequorum quorum notify");
  135. return (0);
  136. }
  137. /*
  138. * Called when config node list reply is received. Vote is set to value returned by server (and can
  139. * be overwriten by algorithm).
  140. *
  141. * Callback should return 0 on success or -1 on failure (-> disconnect client).
  142. */
  143. int
  144. qdevice_net_algo_test_config_node_list_reply_received(struct qdevice_net_instance *instance,
  145. uint32_t seq_number, int initial, enum tlv_vote *vote)
  146. {
  147. qdevice_log(LOG_INFO, "algo-test: Config node list reply");
  148. return (0);
  149. }
  150. /*
  151. * Called when membership node list reply (reply for votequorum votequorum_nodelist_notify_fn)
  152. * is received. Vote is set to value returned by server (and can be overwriten by algorithm).
  153. *
  154. * Also if server returned TLV_VOTE_ASK_LATER, it's good idea to create timer (call timer_list_add
  155. * with instance->main_timer_list parameter) and ask for reply (qdevice_net_send_ask_for_vote).
  156. * Another option may be to wait for vote_info message (if server algorithm is configured so).
  157. *
  158. * Callback should return 0 on success or -1 on failure (-> disconnect client).
  159. */
  160. int
  161. qdevice_net_algo_test_membership_node_list_reply_received(struct qdevice_net_instance *instance,
  162. uint32_t seq_number, const struct tlv_ring_id *ring_id, enum tlv_vote *vote)
  163. {
  164. qdevice_log(LOG_INFO, "algo-test: Membership node list reply");
  165. return (0);
  166. }
  167. /*
  168. * Called when quorum node list reply (reply for votequorum votequorum_quorum_notify_fn)
  169. * is received. Vote is set to value returned by server (and can be overwriten by algorithm).
  170. *
  171. * Callback should return 0 on success or -1 on failure (-> disconnect client).
  172. */
  173. int
  174. qdevice_net_algo_test_quorum_node_list_reply_received(struct qdevice_net_instance *instance,
  175. uint32_t seq_number, enum tlv_vote *vote)
  176. {
  177. qdevice_log(LOG_INFO, "algo-test: Quorum node list reply");
  178. return (0);
  179. }
  180. /*
  181. * Called when reply for ask for vote message was received.
  182. * Vote is set to value returned by server (and can be overwriten by algorithm).
  183. *
  184. * Callback should return 0 on success or -1 on failure (-> disconnect client).
  185. */
  186. int
  187. qdevice_net_algo_test_ask_for_vote_reply_received(struct qdevice_net_instance *instance,
  188. uint32_t seq_number, enum tlv_vote *vote)
  189. {
  190. qdevice_log(LOG_INFO, "algo-test: Ask for vote reply received");
  191. return (0);
  192. }
  193. /*
  194. * Called when vote info message from server was received.
  195. * Vote is set to value sent by server (and can be overwriten by algorithm).
  196. *
  197. * Callback should return 0 on success or -1 on failure (-> disconnect client).
  198. */
  199. int
  200. qdevice_net_algo_test_vote_info_received(struct qdevice_net_instance *instance,
  201. uint32_t seq_number, enum tlv_vote *vote)
  202. {
  203. qdevice_log(LOG_INFO, "algo-test: Vote info received");
  204. return (0);
  205. }
  206. /*
  207. * Called when echo reply message was received.
  208. * is_expected_seq_number is set to 1 if received seq_number was equal to last sent echo request.
  209. *
  210. * Callback should return 0 on success or -1 on failure (-> disconnect client).
  211. */
  212. int
  213. qdevice_net_algo_test_echo_reply_received(struct qdevice_net_instance *instance,
  214. uint32_t seq_number, int is_expected_seq_number)
  215. {
  216. qdevice_log(LOG_INFO, "algo-test: Echo reply received");
  217. return (is_expected_seq_number ? 0 : -1);
  218. }
  219. /*
  220. * Called when client is about to send echo request but echo reply to previous echo request
  221. * was not yet received.
  222. *
  223. * Callback should return 0 if processing should continue (echo request is not send but timer is
  224. * scheduled again) otherwise -1 (-> disconnect client).
  225. */
  226. int
  227. qdevice_net_algo_test_echo_reply_not_received(struct qdevice_net_instance *instance)
  228. {
  229. qdevice_log(LOG_INFO, "algo-test: Echo reply not received");
  230. return (-1);
  231. }
  232. /*
  233. * Called when client disconnect from server.
  234. *
  235. * disconnect_reason contains one of QDEVICE_NET_DISCONNECT_REASON_
  236. * try_reconnect can be set to non zero value if reconnect to server should be tried
  237. * vote (default TLV_VOTE_NO_CHANGE) can be set to update voting timer
  238. *
  239. * Callback should return 0 on success, -1 on failure (-> force exit)
  240. */
  241. int
  242. qdevice_net_algo_test_disconnected(struct qdevice_net_instance *instance,
  243. enum qdevice_net_disconnect_reason disconnect_reason, int *try_reconnect, enum tlv_vote *vote)
  244. {
  245. qdevice_log(LOG_INFO, "algo-test: Disconnected");
  246. return (0);
  247. }
  248. /*
  249. * Called when qdevice-net is going down.
  250. */
  251. void
  252. qdevice_net_algo_test_destroy(struct qdevice_net_instance *instance)
  253. {
  254. qdevice_log(LOG_INFO, "algo-test: Destroy");
  255. }
  256. static struct qdevice_net_algorithm qdevice_net_algo_test = {
  257. .init = qdevice_net_algo_test_init,
  258. .connected = qdevice_net_algo_test_connected,
  259. .config_node_list_changed = qdevice_net_algo_test_config_node_list_changed,
  260. .votequorum_node_list_notify = qdevice_net_algo_test_votequorum_node_list_notify,
  261. .votequorum_quorum_notify = qdevice_net_algo_test_votequorum_quorum_notify,
  262. .config_node_list_reply_received = qdevice_net_algo_test_config_node_list_reply_received,
  263. .membership_node_list_reply_received = qdevice_net_algo_test_membership_node_list_reply_received,
  264. .quorum_node_list_reply_received = qdevice_net_algo_test_quorum_node_list_reply_received,
  265. .ask_for_vote_reply_received = qdevice_net_algo_test_ask_for_vote_reply_received,
  266. .vote_info_received = qdevice_net_algo_test_vote_info_received,
  267. .echo_reply_received = qdevice_net_algo_test_echo_reply_received,
  268. .echo_reply_not_received = qdevice_net_algo_test_echo_reply_not_received,
  269. .disconnected = qdevice_net_algo_test_disconnected,
  270. .destroy = qdevice_net_algo_test_destroy,
  271. };
  272. int
  273. qdevice_net_algo_test_register(void)
  274. {
  275. return (qdevice_net_algorithm_register(TLV_DECISION_ALGORITHM_TYPE_TEST, &qdevice_net_algo_test));
  276. }