Viewing: liblnetconfig.h

/* SPDX-License-Identifier: LGPL-2.1+ */

/*
 * Copyright (c) 2014, 2017, Intel Corporation.
 */

/*
 * This file is part of Lustre, http://www.lustre.org/
 *
 * Author: Amir Shehata <amir.shehata@intel.com>
 */

#ifndef LIB_LNET_CONFIG_API_H
#define LIB_LNET_CONFIG_API_H

#include <errno.h>
#include <net/if.h>
#include <stdbool.h>
#include <sys/socket.h>
#include <yaml.h>
#include <netlink/netlink.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/ctrl.h>

#include <libcfs/util/ioctl.h>
#include <libcfs/util/string.h>
#include <linux/lnet/lnet-dlc.h>
#include <linux/lnet/lnetctl.h>
#include <linux/lnet/nidstr.h>

#define LUSTRE_CFG_RC_NO_ERR			 0 /* success */
#define LUSTRE_CFG_RC_BAD_PARAM			-EINVAL /* 22 */
#define LUSTRE_CFG_RC_MISSING_PARAM		-EFAULT /* 14 */
#define LUSTRE_CFG_RC_OUT_OF_RANGE_PARAM	-ERANGE /* 34 */
#define LUSTRE_CFG_RC_OUT_OF_MEM		-ENOMEM /* 12 */
#define LUSTRE_CFG_RC_GENERIC_ERR		-ENODATA /* 61 */
#define LUSTRE_CFG_RC_NO_MATCH			-ENOMSG /* 42 */
#define LUSTRE_CFG_RC_MATCH			-EXFULL /* 54 */
#define LUSTRE_CFG_RC_SKIP			-EBADSLT /* 57 */
#define LUSTRE_CFG_RC_LAST_ELEM			-ECHRNG /* 48 */
#define LUSTRE_CFG_RC_MARSHAL_FAIL		-ENOSTR /* 60 */

#define CONFIG_CMD		"configure"
#define UNCONFIG_CMD		"unconfigure"
#define ADD_CMD			"add"
#define DEL_CMD			"del"
#define SHOW_CMD		"show"
#define DBG_CMD			"dbg"
#define MANAGE_CMD		"manage"

#define MAX_NUM_IPS		128
#define INT_STRING_LEN		23
#define LNET_DEFAULT_INDENT	6

/* LNet module parameter path */
#define modparam_path "/sys/module/lnet/parameters/"

/* LND module parameter paths */
#define o2iblnd_modparam_path "/sys/module/ko2iblnd/parameters/"
#define socklnd_modparam_path "/sys/module/ksocklnd/parameters/"
#define kfilnd_modparam_path "/sys/module/kkfilnd/parameters/"
#define gnilnd_modparam_path "/sys/module/kgnilnd/parameters/"

#define gni_nid_path "/proc/cray_xt/"

enum lnetctl_cmd {
	LNETCTL_CONFIG_CMD	= 1,
	LNETCTL_UNCONFIG_CMD	= 2,
	LNETCTL_ADD_CMD		= 3,
	LNETCTL_DEL_CMD		= 4,
	LNETCTL_SHOW_CMD	= 5,
	LNETCTL_DBG_CMD		= 6,
	LNETCTL_MANAGE_CMD	= 7,
	LNETCTL_LAST_CMD
};

/*
 * Max number of nids we'll configure for a single peer via a single DLC
 * operation
 */
#define LNET_MAX_NIDS_PER_PEER 128

struct lnet_dlc_network_descr {
	struct list_head network_on_rule;
	__u32 nw_id;
	struct list_head nw_intflist;
};

struct lnet_dlc_intf_descr {
	struct list_head intf_on_network;
	char intf_name[LNET_MAX_STR_LEN];
	struct cfs_expr_list *cpt_expr;
};

/*
 * lustre_lnet_ip2nets
 *	Describes an ip2nets rule. This can be on a list of rules.
 */
struct lustre_lnet_ip2nets {
	struct lnet_dlc_network_descr ip2nets_net;
	struct list_head ip2nets_ip_ranges;
};

/*
 * lustre_lnet_ip_range_descr
 *	Describes an IP range.
 *	For IPv4: Each octet is an expression (ipr_expr)
 *	For IPv6: Single address or CIDR netmask (ipr_addr, ipr_netmask)
 */
struct lustre_lnet_ip_range_descr {
	struct list_head ipr_entry;
	struct list_head ipr_expr;	/* IPv4 expression list */
	bool ipr_is_ipv6;		/* true if IPv6, false if IPv4 */
	union {
		struct in_addr ipv4;
		struct in6_addr ipv6;
	} ipr_addr;			/* IPv6 base address */
	union {
		struct in_addr ipv4;
		struct in6_addr ipv6;
	} ipr_netmask;			/* IPv6 netmask */
	union {
		struct in_addr ipv4;
		struct in6_addr ipv6;
	} ipr_netaddr;			/* IPv6 network address */
	__u8 ipr_prefix_len;		/* IPv6 prefix length */
};

/* This UDSP structures need to match the kernel space structures
 * in order for the marshall and unmarshall functions to be the same.
 */

/* Net is described as a
 *  1. net type
 *  2. num range
 */
struct lnet_ud_net_descr {
	__u32 udn_net_type;
	struct list_head udn_net_num_range;
};

/* each NID range is defined as
 *  1. net descriptor
 *  2. address range descriptor
 */
struct lnet_ud_nid_descr {
	struct lnet_ud_net_descr ud_net_id;
	struct list_head ud_addr_range;
};

/* a UDSP rule can have up to three user defined NID descriptors
 *	- src: defines the local NID range for the rule
 *	- dst: defines the peer NID range for the rule
 *	- rte: defines the router NID range for the rule
 *
 * An action union defines the action to take when the rule
 * is matched
 */
struct lnet_udsp {
	struct list_head udsp_on_list;
	__u32 udsp_idx;
	struct lnet_ud_nid_descr udsp_src;
	struct lnet_ud_nid_descr udsp_dst;
	struct lnet_ud_nid_descr udsp_rte;
	enum lnet_udsp_action_type udsp_action_type;
	union {
		__u32 udsp_priority;
	} udsp_action;
};

/* This union is passed from lnetctl to fill the action union in udsp
 * structure
 * TODO: The idea here is if we add extra actions, ex: drop, it can be
 * added to the union
 */
union lnet_udsp_action {
	int udsp_priority;
};

/* forward declaration of the cYAML structure. */
struct cYAML;

/*
 * lustre_lnet_config_lib_init()
 *   Initialize the Library to enable communication with the LNET kernel
 *   module.  Returns the device ID or -EINVAL if there is an error
 */
int lustre_lnet_config_lib_init();

/*
 * lustre_lnet_config_lib_uninit
 *	Uninitialize the DLC Library
 */
void lustre_lnet_config_lib_uninit();

/*
 * lustre_lnet_config_ni_system
 *   Initialize/Uninitialize the lnet NI system.
 *
 *   up - whehter to init or uninit the system
 *   load_ni_from_mod - load NI from mod params.
 *   seq_no - sequence number of the request
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by
 *            caller
 */
int lustre_lnet_config_ni_system(bool up, bool load_ni_from_mod,
				 int seq_no, struct cYAML **err_rc);

/*
 * lustre_lnet_config_route
 *   Send down an IOCTL to the kernel to configure the route
 *
 *   nw - network
 *   gw - gateway
 *   hops - number of hops passed down by the user
 *   prio - priority of the route
 *   seq_no - sequence number of the request
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by caller
 */
int lustre_lnet_config_route(char *nw, char *gw, int hops, int prio,
			     int seq_no, struct cYAML **err_rc);

/*
 * lustre_lnet_del_route
 *   Send down an IOCTL to the kernel to delete a route
 *
 *   nw - network
 *   gw - gateway
 *   seq_no - sequence number of the request
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by caller
 */
int lustre_lnet_del_route(char *nw, char *gw, int seq_no,
			  struct cYAML **err_rc);

/*
 * lustre_lnet_show_route
 *   Send down an IOCTL to the kernel to show routes
 *   This function will get one route at a time and filter according to
 *   provided parameters. If no routes are available then it will dump all
 *   routes that are in the system.
 *
 *   nw - network.  Optional.  Used to filter output
 *   gw - gateway. Optional. Used to filter ouptut
 *   hops - number of hops passed down by the user
 *          Optional.  Used to filter output.
 *   prio - priority of the route.  Optional.  Used to filter output.
 *   detail - flag to indicate whether detail output is required
 *   seq_no - sequence number of the request
 *   show_rc - [OUT] The show output in YAML.  Must be freed by caller.
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by caller
 *   backup - true to output only what's necessary for reconfiguring
 *	      a node.
 */
int lustre_lnet_show_route(char *nw, char *gw,
			   int hops, int prio, int detail,
			   int seq_no, struct cYAML **show_rc,
			   struct cYAML **err_rc, bool backup);

/*
 * lustre_lnet_config_ni
 *   Send down an IOCTL to configure a network interface. It implicitly
 *   creates a network if one doesn't exist..
 *
 *   nw_descr - network and interface descriptor
 *   global_cpts - globally defined CPTs
 *   ip2net - this parameter allows configuring multiple networks.
 *	it takes precedence over the net and intf parameters
 *   tunables - LND tunables
 *   seq_no - sequence number of the request
 *   lnd_tunables - lnet specific tunable parameters
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by caller
 */
int lustre_lnet_config_ni(struct lnet_dlc_network_descr *nw_descr,
			  struct cfs_expr_list *global_cpts,
			  char *ip2net,
			  struct lnet_ioctl_config_lnd_tunables *tunables,
			  int seq_no, struct cYAML **err_rc);

/*
 * lustre_lnet_del_ni
 *   Send down an IOCTL to delete a network interface. It implicitly
 *   deletes a network if it becomes empty of nis
 *
 *   nw  - network and interface list
 *   seq_no - sequence number of the request
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by caller
 */
int lustre_lnet_del_ni(struct lnet_dlc_network_descr *nw,
		       int seq_no, struct cYAML **err_rc);

/*
 * lustre_lnet_show_net
 *   Send down an IOCTL to show networks.
 *   This function will use the nw paramter to filter the output.  If it's
 *   not provided then all networks are listed.
 *
 *   nw - network to show.  Optional.  Used to filter output.
 *   detail - flag to indicate if we require detail output.
 *   seq_no - sequence number of the request
 *   show_rc - [OUT] The show output in YAML.  Must be freed by caller.
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by caller
 *   backup - true to output only what's necessary for reconfiguring
 *	      a node.
 */
int lustre_lnet_show_net(char *nw, int detail, int seq_no,
			 struct cYAML **show_rc, struct cYAML **err_rc,
			 bool backup);

/*
 * lustre_lnet_config_routing
 *   Send down an IOCTL to enable or diable routing
 *
 *   enable - 1 to enable routing, 0 to disable routing
 *   seq_no - sequence number of the request
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by caller
 */
int lustre_lnet_config_routing(int enable, int seq_no,
			       struct cYAML **err_rc);

/*
 * lustre_lnet_config_numa_range
 *   Set the NUMA range which impacts the NIs to be selected
 *   during sending. If the NUMA range is large the NUMA
 *   distance between the message memory and the NI becomes
 *   less significant. The NUMA range is a relative number
 *   with no other meaning besides allowing a wider breadth
 *   for picking an NI to send from.
 *
 *   range - numa range value.
 *   seq_no - sequence number of the request
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by
 *   caller
 */
int lustre_lnet_config_numa_range(int range, int seq_no,
				  struct cYAML **err_rc);

/*
 * lustre_lnet_show_num_range
 *   Get the currently set NUMA range
 *
 *   seq_no - sequence number of the request
 *   show_rc - [OUT] struct cYAML tree containing NUMA range info
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by
 *   caller
 */
int lustre_lnet_show_numa_range(int seq_no, struct cYAML **show_rc,
				struct cYAML **err_rc);

/*
 * lustre_lnet_config_ni_healthv
 *   set the health value of the NI. -1 resets the value to maximum.
 *
 *   value: health value to set.
 *   all: true to set all local NIs to that value.
 *   ni_nid: NI NID to set its health value. all parameter always takes
 *   precedence
 *   seq_no - sequence number of the request
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by
 *   caller
 */
int lustre_lnet_config_ni_healthv(int value, bool all, char *ni_nid,
				  int seq_no, struct cYAML **err_rc);


/* lustre_lnet_config_ni_conns_per_peer
 *   set the conns_per_peer value of the NI. Valid range is specific to
 *   network type.
 *
 *   value: conns_per_peer value to set.
 *   all: true to set all local NIs to that value.
 *   ni_nid: NI NID to set its conns_per_peer value. 'all' parameter always
 *   takes precedence
 *   seq_no - sequence number of the request
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by
 *   caller
 */
int lustre_lnet_config_ni_conns_per_peer(int value, bool all, char *ni_nid,
					 int seq_no, struct cYAML **err_rc);

/*
 * lustre_lnet_config_peer_ni_healthv
 *   set the health value of the peer NI. -1 resets the value to maximum.
 *
 *   value: health value to set.
 *   all: true to set all local NIs to that value.
 *   pni_nid: Peer NI NID to set its health value. all parameter always takes
 *   precedence
 *   seq_no - sequence number of the request
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by
 *   caller
 */
int lustre_lnet_config_peer_ni_healthv(int value, bool all, char *pni_nid,
				       int seq_no, struct cYAML **err_rc);

/*
 * lustre_lnet_config_recov_intrv
 *   set the recovery interval in seconds. That's the interval to ping an
 *   unhealthy interface.
 *
 *   intrv - recovery interval value to configure
 *   seq_no - sequence number of the request
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by
 *   caller
 */
int lustre_lnet_config_recov_intrv(int intrv, int seq_no, struct cYAML **err_rc);

/*
 * lustre_lnet_show_recov_intrv
 *    show the recovery interval set in the system
 *
 *   seq_no - sequence number of the request
 *   show_rc - [OUT] struct cYAML tree containing health sensitivity info
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by
 *   caller
 */
int lustre_lnet_show_recov_intrv(int seq_no, struct cYAML **show_rc,
				 struct cYAML **err_rc);

/*
 * lustre_lnet_config_rtr_sensitivity
 *   sets the router sensitivity percentage. If the percentage health
 *   of a router interface drops below that it's considered failed
 *
 *   sen - sensitivity value to configure
 *   seq_no - sequence number of the request
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by
 *   caller
 */
int lustre_lnet_config_rtr_sensitivity(int sen, int seq_no, struct cYAML **err_rc);

/*
 * lustre_lnet_config_hsensitivity
 *   sets the health sensitivity; the value by which to decrement the
 *   health value of a local or peer NI. If 0 then health is turned off
 *
 *   sen - sensitivity value to configure
 *   seq_no - sequence number of the request
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by
 *   caller
 */
int lustre_lnet_config_hsensitivity(int sen, int seq_no, struct cYAML **err_rc);

/*
 * lustre_lnet_show_hsensitivity
 *    show the health sensitivity in the system
 *
 *   seq_no - sequence number of the request
 *   show_rc - [OUT] struct cYAML tree containing health sensitivity info
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by
 *   caller
 */
int lustre_lnet_show_hsensitivity(int seq_no, struct cYAML **show_rc,
				  struct cYAML **err_rc);

/*
 * lustre_lnet_show_rtr_sensitivity
 *    show the router sensitivity percentage in the system
 *
 *   seq_no - sequence number of the request
 *   show_rc - [OUT] struct cYAML tree containing health sensitivity info
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by
 *   caller
 */
int lustre_lnet_show_rtr_sensitivity(int seq_no, struct cYAML **show_rc,
				     struct cYAML **err_rc);

/* lustre_lnet_config_lnd_timeout
 *   sets the LND timeout which defines how long the LND should take to complete
 *   a network transaction, by writing the timeout value to the sysfs file
 *   (usually under /sys/module/<lnd>/parameters/).
 *
 *   timeout - timeout value to configure, in seconds
 *   net_type - LND id to configure the timeout on
 *   seq_no - sequence number of the request
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by
 *   caller
 */
int lustre_lnet_config_lnd_timeout(int timeout, __u32 net_type, int seq_no,
				   struct cYAML **err_rc);

/*
 * lustre_lnet_config_transaction_to
 *   sets the timeout after which a message expires or a timeout event is
 *   propagated for an expired response.
 *
 *   timeout - timeout value to configure
 *   seq_no - sequence number of the request
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by
 *   caller
 */
int lustre_lnet_config_transaction_to(int timeout, int seq_no, struct cYAML **err_rc);

/*
 * lustre_lnet_show_transaction_to
 *    show the transaction timeout in the system
 *
 *   seq_no - sequence number of the request
 *   show_rc - [OUT] struct cYAML tree containing transaction timeout info
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by
 *   caller
 */
int lustre_lnet_show_transaction_to(int seq_no, struct cYAML **show_rc,
				    struct cYAML **err_rc);

/*
 * lustre_lnet_config_retry_count
 *   sets the maximum number of retries to resend a message
 *
 *   count - maximum value to configure
 *   seq_no - sequence number of the request
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by
 *   caller
 */
int lustre_lnet_config_retry_count(int count, int seq_no, struct cYAML **err_rc);

/*
 * lustre_lnet_show_retry_count
 *    show current maximum number of retries in the system
 *
 *   seq_no - sequence number of the request
 *   show_rc - [OUT] struct cYAML tree containing retry count info
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by
 *   caller
 */
int lustre_lnet_show_retry_count(int seq_no, struct cYAML **show_rc,
				 struct cYAML **err_rc);

int lustre_lnet_show_lnd_timeout(int seq_no, struct cYAML **show_rc,
				 struct cYAML **err_rc);

int lustre_lnet_show_local_ni_recovq(int seq_no, struct cYAML **show_rc,
				     struct cYAML **err_rc);

int lustre_lnet_show_peer_ni_recovq(int seq_no, struct cYAML **show_rc,
				    struct cYAML **err_rc);
int lustre_lnet_config_response_tracking(int count, int seq_no,
					 struct cYAML **err_rc);
int lustre_lnet_show_response_tracking(int seq_no, struct cYAML **show_rc,
				       struct cYAML **err_rc);
int lustre_lnet_config_recovery_limit(int val, int seq_no,
				      struct cYAML **err_rc);
int lustre_lnet_show_recovery_limit(int seq_no, struct cYAML **show_rc,
				    struct cYAML **err_rc);
int lustre_lnet_show_max_recovery_ping_interval(int seq_no,
						struct cYAML **show_rc,
						struct cYAML **err_rc);

/*
 * lustre_lnet_config_max_intf
 *   Sets the maximum number of interfaces per node. this tunable is
 *   primarily useful for sanity checks prior to allocating memory.
 *
 *   max - maximum value to configure
 *   seq_no - sequence number of the request
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by
 *   caller
 */
int lustre_lnet_config_max_intf(int max, int seq_no, struct cYAML **err_rc);

/*
 * lustre_lnet_show_max_intf
 *    show current maximum interface setting
 *
 *   seq_no - sequence number of the request
 *   show_rc - [OUT] struct cYAML tree containing NUMA range info
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by
 *   caller
 */
int lustre_lnet_show_max_intf(int seq_no, struct cYAML **show_rc,
			      struct cYAML **err_rc);

/*
 * lustre_lnet_calc_service_id
 *    Calculate the lustre service id to be used for qos
 */
int lustre_lnet_calc_service_id(__u64 *service_id);

/*
 * lustre_lnet_setup_mrrouting
 *    configure linux routing tables for tcp interfaces
 *
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by
 *   caller
 */
int lustre_lnet_setup_mrrouting(struct cYAML **err_rc);

/*
 * lustre_lnet_setup_sysctl
 *    enable  linux sysctl settings configured in /etc/lnet-sysctl.conf
 *
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by
 *   caller
 */
int lustre_lnet_setup_sysctl(struct cYAML **err_rc);

/*
 * lustre_lnet_config_discovery
 *   Enable or disable peer discovery. Peer discovery is enabled by default.
 *
 *   enable - non-0 enables, 0 disables
 *   seq_no - sequence number of the request
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by
 *   caller
 */
int lustre_lnet_config_discovery(int enable, int seq_no, struct cYAML **err_rc);

/*
 * lustre_lnet_show_discovery
 *    show current peer discovery setting
 *
 *   seq_no - sequence number of the request
 *   show_rc - [OUT] struct cYAML tree containing NUMA range info
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by
 *   caller
 */
int lustre_lnet_show_discovery(int seq_no, struct cYAML **show_rc,
			       struct cYAML **err_rc);

/*
 * lustre_lnet_config_drop_asym_route
 *   Drop or accept asymmetrical route messages. Accept by default.
 *
 *   drop - non-0 drops, 0 accepts
 *   seq_no - sequence number of the request
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by
 *   caller
 */
int lustre_lnet_config_drop_asym_route(int drop, int seq_no,
				       struct cYAML **err_rc);

/*
 * lustre_lnet_show_drop_asym_route
 *    show current drop asym route setting
 *
 *   seq_no - sequence number of the request
 *   show_rc - [OUT] struct cYAML tree containing NUMA range info
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by
 *   caller
 */
int lustre_lnet_show_drop_asym_route(int seq_no, struct cYAML **show_rc,
				     struct cYAML **err_rc);

/*
 * lustre_lnet_config_buffers
 *   Send down an IOCTL to configure routing buffer sizes.  A value of 0 means
 *   default that particular buffer to default size. A value of -1 means
 *   leave the value of the buffer un changed.
 *
 *   tiny - tiny buffers
 *   small - small buffers
 *   large - large buffers.
 *   seq_no - sequence number of the request
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by caller
 */
int lustre_lnet_config_buffers(int tiny, int small, int large,
			       int seq_no, struct cYAML **err_rc);

/*
 * lustre_lnet_config_max_recovery_ping_interval
 *   Set the maximum recovery ping interval.
 *
 *   interval - interval value in seconds
 *   seq_no - sequence number of the request
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by caller
 */
int lustre_lnet_config_max_recovery_ping_interval(int interval, int seq_no,
						  struct cYAML **err_rc);

/*
 * lustre_lnet_show_routing
 *   Send down an IOCTL to dump buffers and routing status
 *   This function is used to dump buffers for all CPU partitions.
 *
 *   seq_no - sequence number of the request
 *   show_rc - [OUT] The show output in YAML.  Must be freed by caller.
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by caller
 *   backup - true to output only what's necessary for reconfiguring
 *	      a node.
 */
int lustre_lnet_show_routing(int seq_no, struct cYAML **show_rc,
			     struct cYAML **err_rc, bool backup);

/*
 * lustre_lnet_show_stats
 *   Shows internal LNET statistics.  This is useful to display the
 *   current LNET activity, such as number of messages route, etc
 *
 *     seq_no - sequence number of the command
 *     show_rc - YAML structure of the resultant show
 *     err_rc - YAML strucutre of the resultant return code.
 */
int lustre_lnet_show_stats(int seq_no, struct cYAML **show_rc,
			   struct cYAML **err_rc);

/*
 * lustre_lnet_reset_stats
 *   Resets internal LNET statistics.
 *
 *     err_rc - YAML strucutre of the resultant return code.
 */
int lustre_lnet_reset_stats(int seq_no, struct cYAML **err_rc);

/*
 * lustre_lnet_modify_peer
 *  Handle a peer config or delete operation.
 *
 *  Config Operation:
 *  Add a peer NID to a peer with primary NID pnid. 
 *  If the provided primary NID is unique, then a new peer is
 *  created with this primary NID, and the NIDs in the NID list are added as
 *  secondary NIDs to this new peer.
 *  If any of the NIDs in the NID list are not unique then the operation
 *  fails. Some peer NIDs might have already been added. It's the responsibility
 *  of the caller of this API to remove the added NIDs if so desired.
 *
 *  Delete Operation:
 *  Delete the NIDs given in the NID list from the peer with the primary NID
 *  pnid. If pnid is NULL, or it doesn't identify a peer, the operation fails,
 *  and no change happens to the system.
 *  The operation is aborted on the first NID that fails to be deleted.
 *
 *	prim_nid - The desired primary NID of a new peer, or the primary NID of
 *		   an existing peer.
 *	nids - a comma separated string of nids
 *	is_mr - Specifies whether this peer is MR capable.
 *	cmd - CONFIG or DELETE
 *	force - whether force-deleting a peer with locked primary nid
 *	seq_no - sequence number of the command
 *	err_rc - YAML structure of the resultant return code
 */
int lustre_lnet_modify_peer(char *prim_nid, char *nids, bool is_mr, int cmd,
			    int force, int seq_no, struct cYAML **err_rc);

/*
 * lustre_lnet_show_peer
 *   Show the peer identified by nid, knid. If knid is NULL all
 *   peers in the system are shown.
 *
 *     knid - A NID of the peer
 *     detail - display detailed information
 *     seq_no - sequence number of the command
 *     show_rc - YAML structure of the resultant show
 *     err_rc - YAML strucutre of the resultant return code.
 *     backup - true to output only what's necessary for reconfiguring
 *		a node.
 *
 */
int lustre_lnet_show_peer(char *knid, int detail, int seq_no,
			  struct cYAML **show_rc, struct cYAML **err_rc,
			  bool backup);

/*
 * lustre_lnet_list_peer
 *   List the known peers.
 *
 *     seq_no - sequence number of the command
 *     show_rc - YAML structure of the resultant show
 *     err_rc - YAML strucutre of the resultant return code.
 *
 */
int lustre_lnet_list_peer(int seq_no,
			  struct cYAML **show_rc, struct cYAML **err_rc);

/* lustre_lnet_ping_nid
 *   Ping the nid list, pnids.
 *
 *    pnids - NID list to ping.
 *    src_nidstr - source NID
 *    timeout - timeout(seconds) for ping.
 *    seq_no - sequence number of the command.
 *    show_rc - YAML structure of the resultant show.
 *    err_rc - YAML strucutre of the resultant return code.
 *
 */
int lustre_lnet_ping_nid(char *pnid, char *src_nidstr, int timeout, int seq_no,
			struct cYAML **show_rc, struct cYAML **err_rc);

/* lustre_lnet_discover_nid
 *   Discover the nid list, pnids.
 *
 *    pnids - NID list to discover.
 *    force - force discovery.
 *    seq_no - sequence number of the command.
 *    show_rc - YAML structure of the resultant show.
 *    err_rc - YAML strucutre of the resultant return code.
 *
 */
int lustre_lnet_discover_nid(char *pnid, int force, int seq_no,
			     struct cYAML **show_rc, struct cYAML **err_rc);

/*
 * lustre_yaml_config
 *   Parses the provided YAML file and then calls the specific APIs
 *   to configure the entities identified in the file
 *
 *   f - YAML file
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by caller
 */
int lustre_yaml_config(char *f, int len, struct cYAML **err_rc);

/*
 * lustre_yaml_del
 *   Parses the provided YAML file and then calls the specific APIs
 *   to delete the entities identified in the file
 *
 *   f - YAML file
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by caller
 */
int lustre_yaml_del(char *f, int len, struct cYAML **err_rc);

/*
 * lustre_yaml_show
 *   Parses the provided YAML file and then calls the specific APIs
 *   to show the entities identified in the file
 *
 *   f - YAML file
 *   show_rc - [OUT] The show output in YAML.  Must be freed by caller.
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by caller
 */
int lustre_yaml_show(char *f, int len, struct cYAML **show_rc,
		     struct cYAML **err_rc);

/*
 * lustre_yaml_exec
 *   Parses the provided YAML file and then calls the specific APIs
 *   to execute the entities identified in the file
 *
 *   f - YAML file
 *   show_rc - [OUT] The show output in YAML.  Must be freed by caller.
 *   err_rc - [OUT] struct cYAML tree describing the error. Freed by caller
 */
int lustre_yaml_exec(char *f, int len, struct cYAML **show_rc,
		     struct cYAML **err_rc);

struct nid_node {
	char nidstr[LNET_MAX_STR_LEN * 2];
	struct nl_list_head children;
	struct nl_list_head list;
};

int lustre_lnet_parse_nid_range(struct nid_node *head, char *nidstr,
				const char **errmsg);
void lustre_lnet_free_list(struct nid_node *head);

/**
 * yaml_lnet_configure
 *
 *   Shared code for LNet setup and teardown.
 *
 *   flags	- Netlink flags that control setup behavior
 *		  NLM_F_CREATE  - initializes LNet stack
 *		  NLM_F_EXCL	- ignore module params
 *		  0		- tears down LNet stack
 *
 *   msg	  error msg string returned.
 */
int yaml_lnet_configure(int flags, const char **msg);

int yaml_lnet_fault_rule(yaml_document_t *results, __u32 opc, char *src,
			 char *dst, char *local_nid,
			 struct lnet_fault_attr *attr);

/**
 * yaml_emitter_set_output_netlink
 *
 *   Special handling to integrate LNet handling into libyaml.
 *   This function sets up the ability to take the data stored in @emitter
 *   and formats into a netlink packet to send to the kernel.
 *
 *   emitter	- YAML emitter containing what the user specified
 *   nl		- Netlink socket to be used by libyaml
 *   family	- Netlink family
 *   version	- notify kernel what version user land supports
 *   cmd	- Netlink command to execute
 *   flags	- Netlink flags
 */
int yaml_emitter_set_output_netlink(yaml_emitter_t *emitter, struct nl_sock *nl,
				    char *family, int version, int cmd,
				    int flags);
/**
 * yaml_emitter_set_streaming_output_netlink
 *
 * Special handling to handle the fact RHEL7 is super old.
 */
int yaml_emitter_set_streaming_output_netlink(yaml_emitter_t *sender,
					      struct nl_sock *nl, char *family,
					      int version, int cmd, int flags,
					      bool stream);

/**
 * yaml_parser_set_input_netlink
 *
 *   Special handling to LNet handling into libyaml.
 *   This function sets up the ability to receive the Netlink data
 *   from the Linux kernel. That data is formated into a YAML document.
 *
 *   parser	- YAML parser that is used to present the data received
 *		  from the kernel in Netlink format.
 *   nl		- should be the Netlink socket receiving data from
 *		  the kernel.
 *   stream	- Handle the case of continuous data coming in.
 */
int yaml_parser_set_input_netlink(yaml_parser_t *parser, struct nl_sock *nl,
				  bool stream);

/**
 * yaml_parser_get_reader_proto_version
 *
 *   This function retrieves the Neltink version the kernel module
 *   is set to.
 *
 *   parser	- YAML parser being used for Netlink communication.
 */
int yaml_parser_get_reader_proto_version(yaml_parser_t *parser);

/**
 * yaml_parser_get_reader_error
 *
 *   By default libyaml reports a generic write error. We need a way
 *   to report better parser errors so we can track down problems.
 *
 *   parser	- YAML parser that has reported an error.
 */
const char *yaml_parser_get_reader_error(yaml_parser_t *parser);

/**
 * yaml_parser_log_error
 *
 *   Helper function to report the parser error to @log.
 *
 *   parser	- YAML parser that has reported an error.
 *   log	- file descriptor to write the error message out to.
 *   errmsg	- Special extra string to append to error message.
 */
void yaml_parser_log_error(yaml_parser_t *parser, FILE *log,
			   const char *errmsg);

/**
 * yaml_emitter_log_error
 *
 *   Helper function to report the emitter error to @log.
 *
 *   emitter	- YAML emitter that has reported an error.
 *   log	- file descriptor to write the error message out to.
 */
void yaml_emitter_log_error(yaml_emitter_t *emitter, FILE *log);

/*
 * yaml_emitter_cleanup - Cleanup request & all memory held by reqeust
 */
void yaml_emitter_cleanup(yaml_emitter_t *request);

/*
 * yaml_parser_cleanup - Cleanup parser & all memory held by parser
 */
void yaml_parser_cleanup(yaml_parser_t *reply);

/**
 * yaml_netlink_setup_emitter
 *
 *   Helper function to setup emitter with Netlink. Needed for
 *   cases where we reuse the @sk.
 *
 *   emitter	- YAML emitter to setup.
 *   sk		- Netlink socket.
 *   family	- Netlink family
 *   version	- Netlink API version
 *   flags	- Netlink flags (NLM_F_*)
 *   op		- Netlink command (*_CMD_*)
 *   stream	- Is the netlink socket reusable
 */
int yaml_netlink_setup_emitter(yaml_emitter_t *output, struct nl_sock *sk,
			       char *family, int version, int flags, int op,
			       bool stream);

/**
 * yaml_netlink_complete_emitter
 *
 *   Helper function to cleanup emitter when done. The netlink socket
 *   is not altered in anyway.
 *
 *   emitter	- YAML emitter to cleanup.
 */
int yaml_netlink_complete_emitter(yaml_emitter_t *output);

/*
 * lustre_lnet_init_nw_descr
 *	initialize the network descriptor structure for use
 */
void lustre_lnet_init_nw_descr(struct lnet_dlc_network_descr *nw_descr);

/*
 * lustre_lnet_parse_interfaces
 *	prase an interface string and populate descriptor structures
 *		intf_str - interface string of the format
 *			<intf>[<expr>], <intf>[<expr>],..
 *		nw_descr - network descriptor to populate
 *		init - True to initialize nw_descr
 */
int lustre_lnet_parse_interfaces(char *intf_str,
				 struct lnet_dlc_network_descr *nw_descr);

/*
 * lustre_lnet_parse_nidstr
 *     This is a small wrapper around cfs_parse_nidlist.
 *         nidstr - A string parseable by cfs_parse_nidlist
 *         lnet_nidlist - An array of lnet_nid_t to hold the nids specified
 *                        by the nidstring.
 *         max_nids - Size of the lnet_nidlist array, and the maximum number of
 *                    nids that can be expressed by the nidstring. If the
 *                    nidstring expands to a larger number of nids than max_nids
 *                    then an error is returned.
 *         err_str - char pointer where we store an informative error
 *                   message when an error is encountered
 *     Returns:
 *         The number (> 0) of lnet_nid_t stored in the supplied array, or
 *         LUSTRE_CFG_RC_BAD_PARAM if:
 *           - nidstr is NULL
 *           - nidstr contains an asterisk. This character is not allowed
 *             because it would cause the size of the expanded nidlist to exceed
 *             the maximum number of nids that is supported by expected callers
 *             of this function.
 *           - cfs_parse_nidlist fails to parse the nidstring
 *           - The nidlist populated by cfs_parse_nidlist is empty
 *           - The nidstring expands to a larger number of nids than max_nids
 *           - The nidstring expands to zero nids
 *         LUSTRE_CFG_RC_OUT_OF_MEM if:
 *           - cfs_expand_nidlist can return ENOMEM. We return out of mem in
 *             this case.
 */
int lustre_lnet_parse_nidstr(char *nidstr, lnet_nid_t *lnet_nidlist,
			     int max_nids, char *err_str);

int lustre_lnet_debug_nidlist(char *nidstr, char *match_nid);
/* lustre_lnet_add_udsp
 *	Add a selection policy.
 *	src - source NID descriptor
 *	dst - destination NID descriptor
 *	rte - router NID descriptor
 *	type - action type
 *	action - union of the action
 *	idx - the index to delete
 *	seq_no - sequence number of the request
 *	err_rc - [OUT] struct cYAML tree describing the error. Freed by
 *               caller
 */
int lustre_lnet_add_udsp(char *src, char *dst, char *rte, char *type,
			 union lnet_udsp_action *action, int idx,
			 int seq_no, struct cYAML **err_rc);

/* lustre_lnet_del_udsp
 *	Delete a net selection policy.
 *	idx - the index to delete
 *	seq_no - sequence number of the request
 *	err_rc - [OUT] struct cYAML tree describing the error. Freed by
 *	caller
 */
int lustre_lnet_del_udsp(unsigned int idx, int seq_no, struct cYAML **err_rc);

/* lustre_lnet_show_udsp
 *	show selection policy.
 *	idx - the index to show. -1 to show all policies
 *	seq_no - sequence number of the request
 *	err_rc - [IN/OUT] struct cYAML tree containing udsp info
 *	err_rc - [OUT] struct cYAML tree describing the error. Freed by
 *	caller
 */
int lustre_lnet_show_udsp(int idx, int seq_no, struct cYAML **show_rc,
			  struct cYAML **err_rc);

/* lustre_lnet_show_peer_debug_info
 *	dump peer debug info
 *	peer_nid - nid of the peer to show
 *	seq_no - sequence number of the request
 *	err_rc - [OUT] struct cYAML tree describing the error. Freed by
 *	caller
 */
int lustre_lnet_show_peer_debug_info(char *peer_nid, int seq_no,
				     struct cYAML **err_rc);

/* lustre_lnet_set_peer_state
 *	set peer state
 *	lpni_nid - primary nid of the peer
 *	seq_no - sequence number of the request
 *	err_rc - [OUT] struct cYAML tree describing the error. Freed by
 *	caller
 */
int lustre_lnet_set_peer_state(int state, char *lpni_nid, int seq_no,
			       struct cYAML **err_rc);

int
lnet_yaml_int_mapping(yaml_event_t *event, yaml_emitter_t *emitter,
		      const char *key, const void *val, int size);
int
lnet_yaml_uint_mapping(yaml_event_t *event, yaml_emitter_t *emitter,
		       const char *key, const void *val, int size);
int
lnet_yaml_bool_mapping(yaml_event_t *event, yaml_emitter_t *emitter,
		       const char *key, const char *val);
int
lnet_yaml_str_mapping(yaml_event_t *event, yaml_emitter_t *emitter,
		      const char *key, const char *val);

int
lustre_lnet_add_intf_descr(struct list_head *list, char *intf, int len);
int
lustre_lnet_add_ip_range(struct list_head *list, char *str_ip_range);
int
lustre_lnet_config_ip2nets(struct lustre_lnet_ip2nets *ip2nets,
			   struct lnet_ioctl_config_lnd_tunables *tunables,
			   struct cfs_expr_list *global_cpts,
			   int seq_no, struct cYAML **err_rc);
void free_intf_descr(struct lnet_dlc_intf_descr *intf_descr);
int lustre_lnet_resolve_ip2nets_rule(struct lustre_lnet_ip2nets *ip2nets,
				     lnet_nid_t **nids, __u32 *nnids,
				     char *err_str, size_t str_len);
int lustre_lnet_kfi_intf2cxi(struct lnet_dlc_intf_descr *intf);
#endif /* LIB_LNET_CONFIG_API_H */