text: /*
   *
   * Copyright 2015-2016, LabN Consulting, L.L.C.
   *
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License
   * as published by the Free Software Foundation; either version 2
   * of the License, or (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License along
   * with this program; see the file COPYING; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
  #ifdef HAVE_CONFIG_H
  #include "config.h"
  #endif
  
  /* stub rfp */
  #include "rfp_internal.h"
  #include "bgpd/rfapi/rfapi.h"
  #include "lib/command.h"
  
  struct rfp_instance_t {
  	struct rfapi_rfp_cfg rfapi_config;
  	struct rfapi_rfp_cb_methods rfapi_callbacks;
  	struct thread_master *master;
  	uint32_t config_var;
  };
  
  struct rfp_instance_t
  	global_rfi; /* dynamically allocate in full implementation */
  
  /***********************************************************************
   * Sample VTY / internal function
   **********************************************************************/
  #define RFP_SHOW_STR "RFP information\n"
  DEFUN (rfp_example_config_value,
         rfp_example_config_value_cmd,
         "rfp example-config-value VALUE",
         RFP_SHOW_STR
         "Example value to be configured\n"
         "Value to display\n")
  {
  	uint32_t value = 0;
  	struct rfp_instance_t *rfi = NULL;
  	rfi = rfapi_get_rfp_start_val(VTY_GET_CONTEXT(bgp)); /* BGP_NODE */
  	assert(rfi != NULL);
  
  	value = strtoul(argv[2]->arg, NULL, 10);
  	if (rfi)
  		rfi->config_var = value;
  	return CMD_SUCCESS;
  }
  
  DEFUN (rfp_holddown_factor,
         rfp_holddown_factor_cmd,
         "rfp holddown-factor (0-4294967295)",
         RFP_SHOW_STR
         "Set Hold-Down Factor as a percentage of registration lifetime.\n"
         "Percentage of registration lifetime\n")
  {
  	struct rfp_instance_t *rfi;
  	uint32_t value = 0;
  
  	value = strtoul((argv[--argc]->arg), NULL, 10);
  	rfi = rfapi_get_rfp_start_val(VTY_GET_CONTEXT(bgp)); /* BGP_NODE */
  	if (!rfi) {
  		vty_out(vty, "VNC not configured\n");
  		return CMD_WARNING;
  	}
  	rfi->rfapi_config.holddown_factor = value;
  	rfapi_rfp_set_configuration(rfi, &rfi->rfapi_config);
  	return CMD_SUCCESS;
  }
  
  
  DEFUN (rfp_full_table_download,
         rfp_full_table_download_cmd,
         "rfp full-table-download <on|off>",
         RFP_SHOW_STR
         "RFP full table download support (default=on)\n"
         "Enable RFP full table download\n"
         "Disable RFP full table download\n")
  {
  	struct rfp_instance_t *rfi;
  	rfapi_rfp_download_type old;
  
  	rfi = rfapi_get_rfp_start_val(VTY_GET_CONTEXT(bgp)); /* BGP_NODE */
  	if (!rfi) {
  		vty_out(vty, "VNC not configured\n");
  		return CMD_WARNING;
  	}
  	old = rfi->rfapi_config.download_type;
  	if (argv[--argc]->arg[1] == 'n' || argv[argc]->arg[1] == 'N')
  		rfi->rfapi_config.download_type = RFAPI_RFP_DOWNLOAD_FULL;
  	else
  		rfi->rfapi_config.download_type = RFAPI_RFP_DOWNLOAD_PARTIAL;
  	if (old != rfi->rfapi_config.download_type)
  		rfapi_rfp_set_configuration(rfi, &rfi->rfapi_config);
  	return CMD_SUCCESS;
  }
  
  static void rfp_vty_install(void)
  {
  	static int installed = 0;
  	if (installed) /* do this only once */
  		return;
  	installed = 1;
  	/* example of new cli command */
  	install_element(BGP_NODE, &rfp_example_config_value_cmd);
  	install_element(BGP_NODE, &rfp_holddown_factor_cmd);
  	install_element(BGP_NODE, &rfp_full_table_download_cmd);
  }
  
  /***********************************************************************
   * RFAPI Callbacks
   **********************************************************************/
  
  /*------------------------------------------
   * rfp_response_cb
   *
   * Callbacks of this type are used to provide asynchronous
   * route updates from RFAPI to the RFP client.
   *
   * response_cb
   *	called to notify the rfp client that a next hop list
   *	that has previously been provided in response to an
   *	rfapi_query call has been updated. Deleted routes are indicated
   *	with lifetime==RFAPI_REMOVE_RESPONSE_LIFETIME.
   *
   *	By default, the routes an NVE receives via this callback include
   *	its own routes (that it has registered). However, these may be
   *	filtered out if the global BGP_VNC_CONFIG_FILTER_SELF_FROM_RSP
   *	flag is set.
   *
   * input:
   *	next_hops	a list of possible next hops.
   *			This is a linked list allocated within the
   *			rfapi. The response_cb callback function is responsible
   *			for freeing this memory via rfapi_free_next_hop_list()
   *			in order to avoid memory leaks.
   *
   *	userdata	value (cookie) originally specified in call to
   *			rfapi_open()
   *
   *------------------------------------------*/
  static void rfp_response_cb(struct rfapi_next_hop_entry *next_hops,
  			    void *userdata)
  {
  	/*
  	 * Identify NVE based on userdata, which is a value passed
  	 * to RFAPI in the rfapi_open call
  	 */
  
  	/* process list of next_hops */
  
  	/* free next hops */
  	rfapi_free_next_hop_list(next_hops);
  	return;
  }
  
  /*------------------------------------------
   * rfp_local_cb
   *
   * Callbacks of this type are used to provide asynchronous
   * route updates from RFAPI to the RFP client.
   *
   * local_cb
   *	called to notify the rfp client that a local route
   *	has been added or deleted. Deleted routes are indicated
   *	with lifetime==RFAPI_REMOVE_RESPONSE_LIFETIME.
   *
   * input:
   *	next_hops	a list of possible next hops.
   *			This is a linked list allocated within the
   *			rfapi. The local_cb callback function is responsible
   *			for freeing this memory via rfapi_free_next_hop_list()
   *			in order to avoid memory leaks.
   *
   *	userdata	value (cookie) originally specified in call to
   *			rfapi_open()
   *
   *------------------------------------------*/
  static void rfp_local_cb(struct rfapi_next_hop_entry *next_hops, void *userdata)
  {
  	/*
  	 * Identify NVE based on userdata, which is a value passed
  	 * to RFAPI in the rfapi_open call
  	 */
  
  	/* process list of local next_hops */
  
  	/* free next hops */
  	rfapi_free_next_hop_list(next_hops);
  	return;
  }
  
  /*------------------------------------------
   * rfp_close_cb
   *
   * Callbacks used to provide asynchronous
   * notification that an rfapi_handle was invalidated
   *
   * input:
   *	pHandle		Firmerly valid rfapi_handle returned to
   *			client via rfapi_open().
   *
   *	reason		EIDRM	handle administratively closed (clear nve ...)
   *			ESTALE	handle invalidated by configuration change
   *
   *------------------------------------------*/
  static void rfp_close_cb(rfapi_handle pHandle, int reason)
  {
  	/* close / invalidate NVE with the pHandle returned by the rfapi_open
  	 * call */
  	return;
  }
  
  /*------------------------------------------
   * rfp_cfg_write_cb
   *
   * This callback is used to generate output for any config parameters
   * that may supported by RFP  via RFP defined vty commands at the bgp
   * level.  See loglevel as an example.
   *
   * input:
   *    vty           -- quagga vty context
   *    rfp_start_val -- value returned by rfp_start
   *
   * output:
   *    to vty, rfp related configuration
   *
   * return value:
   *    lines written
  --------------------------------------------*/
  static int rfp_cfg_write_cb(struct vty *vty, void *rfp_start_val)
  {
  	struct rfp_instance_t *rfi = rfp_start_val;
  	int write = 0;
  	assert(rfp_start_val != NULL);
  	if (rfi->config_var != 0) {
  		vty_out(vty, " rfp example-config-value %u", rfi->config_var);
  		vty_out(vty, "\n");
  		write++;
  	}
  	if (rfi->rfapi_config.holddown_factor != 0) {
  		vty_out(vty, " rfp holddown-factor %u\n",
  			rfi->rfapi_config.holddown_factor);
  		write++;
  	}
  	if (rfi->rfapi_config.download_type == RFAPI_RFP_DOWNLOAD_FULL) {
  		vty_out(vty, " rfp full-table-download on\n");
  		write++;
  	}
  	return write;
  }
  
  /***********************************************************************
   * RFAPI required functions
   **********************************************************************/
  
  /*------------------------------------------
   * rfp_start
   *
   * This function will start the RFP code
   *
   * input:
   *    master    quagga thread_master to tie into bgpd threads
   *
   * output:
   *    cfgp      Pointer to rfapi_rfp_cfg (null = use defaults),
   *              copied by caller, updated via rfp_set_configuration
   *    cbmp      Pointer to rfapi_rfp_cb_methods, may be null
   *              copied by caller, updated via rfapi_rfp_set_cb_methods
   *
   * return value:
   *    rfp_start_val rfp returned value passed on rfp_stop and rfp_cfg_write
   *
  --------------------------------------------*/
  void *rfp_start(struct thread_master *master, struct rfapi_rfp_cfg **cfgp,
  		struct rfapi_rfp_cb_methods **cbmp)
  {
  	memset(&global_rfi, 0, sizeof(struct rfp_instance_t));
  	global_rfi.master = master; /* for BGPD threads */
  
  	/* initilize struct rfapi_rfp_cfg, see rfapi.h */
  	global_rfi.rfapi_config.download_type =
  		RFAPI_RFP_DOWNLOAD_PARTIAL; /* default=partial */
  	global_rfi.rfapi_config.ftd_advertisement_interval =
  		RFAPI_RFP_CFG_DEFAULT_FTD_ADVERTISEMENT_INTERVAL;
  	global_rfi.rfapi_config.holddown_factor =
  		0; /* default: RFAPI_RFP_CFG_DEFAULT_HOLDDOWN_FACTOR */
  	global_rfi.rfapi_config.use_updated_response = 1; /* 0=no */
  	global_rfi.rfapi_config.use_removes = 1;	  /* 0=no */
  
  
  	/* initilize structrfapi_rfp_cb_methods , see rfapi.h */
  	global_rfi.rfapi_callbacks.cfg_cb = rfp_cfg_write_cb;
  	/* no group config */
  	global_rfi.rfapi_callbacks.response_cb = rfp_response_cb;
  	global_rfi.rfapi_callbacks.local_cb = rfp_local_cb;
  	global_rfi.rfapi_callbacks.close_cb = rfp_close_cb;
  
  	if (cfgp != NULL)
  		*cfgp = &global_rfi.rfapi_config;
  	if (cbmp != NULL)
  		*cbmp = &global_rfi.rfapi_callbacks;
  
  	rfp_vty_install();
  
  	return &global_rfi;
  }
  
  /*------------------------------------------
   * rfp_stop
   *
   * This function is called on shutdown to trigger RFP cleanup
   *
   * input:
   *    none
   *
   * output:
   *    none
   *
   * return value:
   *    rfp_start_val
  --------------------------------------------*/
  void rfp_stop(void *rfp_start_val)
  {
  	assert(rfp_start_val != NULL);
  }
  
  /* TO BE REMOVED */
  void rfp_clear_vnc_nve_all(void)
  {
  	return;
  }
  