* number have been allocated.
*/
#define IOCTL_CONFIG_SIZE struct lnet_ioctl_config_data
-#define IOC_LIBCFS_ADD_ROUTE _IOWR(IOC_LIBCFS_TYPE, 81, \
- IOCTL_CONFIG_SIZE)
-#define IOC_LIBCFS_DEL_ROUTE _IOWR(IOC_LIBCFS_TYPE, 82, \
- IOCTL_CONFIG_SIZE)
-#define IOC_LIBCFS_GET_ROUTE _IOWR(IOC_LIBCFS_TYPE, 83, \
- IOCTL_CONFIG_SIZE)
-#define IOC_LIBCFS_ADD_NET _IOWR(IOC_LIBCFS_TYPE, 84, \
- IOCTL_CONFIG_SIZE)
-#define IOC_LIBCFS_DEL_NET _IOWR(IOC_LIBCFS_TYPE, 85, \
- IOCTL_CONFIG_SIZE)
-#define IOC_LIBCFS_GET_NET _IOWR(IOC_LIBCFS_TYPE, 86, \
- IOCTL_CONFIG_SIZE)
-#define IOC_LIBCFS_CONFIG_RTR _IOWR(IOC_LIBCFS_TYPE, 87, \
- IOCTL_CONFIG_SIZE)
-#define IOC_LIBCFS_ADD_BUF _IOWR(IOC_LIBCFS_TYPE, 88, \
- IOCTL_CONFIG_SIZE)
-#define IOC_LIBCFS_GET_BUF _IOWR(IOC_LIBCFS_TYPE, 89, \
- IOCTL_CONFIG_SIZE)
-#define IOC_LIBCFS_GET_PEER_INFO _IOWR(IOC_LIBCFS_TYPE, 90, \
- IOCTL_CONFIG_SIZE)
-#define IOC_LIBCFS_GET_LNET_STATS _IOWR(IOC_LIBCFS_TYPE, 91, \
- IOCTL_CONFIG_SIZE)
-#define IOC_LIBCFS_ADD_PEER_NI _IOWR(IOC_LIBCFS_TYPE, 92, \
- IOCTL_CONFIG_SIZE)
-#define IOC_LIBCFS_DEL_PEER_NI _IOWR(IOC_LIBCFS_TYPE, 93, \
- IOCTL_CONFIG_SIZE)
-#define IOC_LIBCFS_GET_PEER_NI _IOWR(IOC_LIBCFS_TYPE, 94, \
- IOCTL_CONFIG_SIZE)
-#define IOC_LIBCFS_MAX_NR 94
+#define IOC_LIBCFS_ADD_ROUTE _IOWR(IOC_LIBCFS_TYPE, 81, IOCTL_CONFIG_SIZE)
+#define IOC_LIBCFS_DEL_ROUTE _IOWR(IOC_LIBCFS_TYPE, 82, IOCTL_CONFIG_SIZE)
+#define IOC_LIBCFS_GET_ROUTE _IOWR(IOC_LIBCFS_TYPE, 83, IOCTL_CONFIG_SIZE)
+#define IOC_LIBCFS_ADD_NET _IOWR(IOC_LIBCFS_TYPE, 84, IOCTL_CONFIG_SIZE)
+#define IOC_LIBCFS_DEL_NET _IOWR(IOC_LIBCFS_TYPE, 85, IOCTL_CONFIG_SIZE)
+#define IOC_LIBCFS_GET_NET _IOWR(IOC_LIBCFS_TYPE, 86, IOCTL_CONFIG_SIZE)
+#define IOC_LIBCFS_CONFIG_RTR _IOWR(IOC_LIBCFS_TYPE, 87, IOCTL_CONFIG_SIZE)
+#define IOC_LIBCFS_ADD_BUF _IOWR(IOC_LIBCFS_TYPE, 88, IOCTL_CONFIG_SIZE)
+#define IOC_LIBCFS_GET_BUF _IOWR(IOC_LIBCFS_TYPE, 89, IOCTL_CONFIG_SIZE)
+#define IOC_LIBCFS_GET_PEER_INFO _IOWR(IOC_LIBCFS_TYPE, 90, IOCTL_CONFIG_SIZE)
+#define IOC_LIBCFS_GET_LNET_STATS _IOWR(IOC_LIBCFS_TYPE, 91, IOCTL_CONFIG_SIZE)
+#define IOC_LIBCFS_ADD_PEER_NI _IOWR(IOC_LIBCFS_TYPE, 92, IOCTL_CONFIG_SIZE)
+#define IOC_LIBCFS_DEL_PEER_NI _IOWR(IOC_LIBCFS_TYPE, 93, IOCTL_CONFIG_SIZE)
+#define IOC_LIBCFS_GET_PEER_NI _IOWR(IOC_LIBCFS_TYPE, 94, IOCTL_CONFIG_SIZE)
+#define IOC_LIBCFS_ADD_LOCAL_NI _IOWR(IOC_LIBCFS_TYPE, 95, IOCTL_CONFIG_SIZE)
+#define IOC_LIBCFS_DEL_LOCAL_NI _IOWR(IOC_LIBCFS_TYPE, 96, IOCTL_CONFIG_SIZE)
+#define IOC_LIBCFS_GET_LOCAL_NI _IOWR(IOC_LIBCFS_TYPE, 97, IOCTL_CONFIG_SIZE)
+#define IOC_LIBCFS_DBG _IOWR(IOC_LIBCFS_TYPE, 98, IOCTL_CONFIG_SIZE)
+#define IOC_LIBCFS_MAX_NR 98
extern int libcfs_ioctl_data_adjust(struct libcfs_ioctl_data *data);
struct cfs_expr_list *expr_list);
int cfs_expr_list_values(struct cfs_expr_list *expr_list,
int max, __u32 **values);
-static inline void
-cfs_expr_list_values_free(__u32 *values, int num)
-{
- /* This array is allocated by LIBCFS_ALLOC(), so it shouldn't be freed
- * by OBD_FREE() if it's called by module other than libcfs & LNet,
- * otherwise we will see fake memory leak */
- LIBCFS_FREE(values, num * sizeof(values[0]));
-}
-
+void cfs_expr_list_values_free(__u32 *values, int num);
void cfs_expr_list_free(struct cfs_expr_list *expr_list);
int cfs_expr_list_parse(char *str, int len, unsigned min, unsigned max,
struct cfs_expr_list **elpp);
struct cfs_expr_list *expr_list);
int cfs_expr_list_parse(char *str, int len, unsigned min, unsigned max,
struct cfs_expr_list **elpp);
+void cfs_expr_list_free(struct cfs_expr_list *expr_list);
void cfs_expr_list_free_list(struct list_head *list);
int cfs_ip_addr_parse(char *str, int len, struct list_head *list);
int cfs_ip_addr_match(__u32 addr, struct list_head *list);
}
EXPORT_SYMBOL(cfs_expr_list_values);
+void
+cfs_expr_list_values_free(__u32 *values, int num)
+{
+ /* This array is allocated by LIBCFS_ALLOC(), so it shouldn't be freed
+ * by OBD_FREE() if it's called by module other than libcfs & LNet,
+ * otherwise we will see fake memory leak */
+ LIBCFS_FREE(values, num * sizeof(values[0]));
+}
+EXPORT_SYMBOL(cfs_expr_list_values_free);
+
/**
* Frees cfs_range_expr structures of \a expr_list.
*
}
/**
+ * Convert express list (\a expr_list) to an array of all matched values
+ *
+ * \retval N N is total number of all matched values
+ * \retval 0 if expression list is empty
+ * \retval < 0 for failure
+ */
+int
+cfs_expr_list_values(struct cfs_expr_list *expr_list, int max, __u32 **valpp)
+{
+ struct cfs_range_expr *expr;
+ __u32 *val;
+ int count = 0;
+ int i;
+
+ list_for_each_entry(expr, &expr_list->el_exprs, re_link) {
+ for (i = expr->re_lo; i <= expr->re_hi; i++) {
+ if (((i - expr->re_lo) % expr->re_stride) == 0)
+ count++;
+ }
+ }
+
+ if (count == 0) /* empty expression list */
+ return 0;
+
+ if (count > max)
+ return -EINVAL;
+
+ val = calloc(sizeof(val[0]), count);
+ if (val == NULL)
+ return -ENOMEM;
+
+ count = 0;
+ list_for_each_entry(expr, &expr_list->el_exprs, re_link) {
+ for (i = expr->re_lo; i <= expr->re_hi; i++) {
+ if (((i - expr->re_lo) % expr->re_stride) == 0)
+ val[count++] = i;
+ }
+ }
+
+ *valpp = val;
+ return count;
+}
+
+void
+cfs_expr_list_values_free(__u32 *values, int num)
+{
+ /* This array is allocated by LIBCFS_ALLOC(), so it shouldn't be freed
+ * by OBD_FREE() if it's called by module other than libcfs & LNet,
+ * otherwise we will see fake memory leak */
+ free(values);
+}
+
+/**
* Frees cfs_range_expr structures of \a expr_list.
*
* \retval none
*/
-static void
+void
cfs_expr_list_free(struct cfs_expr_list *expr_list)
{
while (!list_empty(&expr_list->el_exprs)) {
#define LNET_MAX_SHOW_NUM_CPT 128
#define LNET_UNDEFINED_HOPS ((__u32) -1)
+/*
+ * To allow for future enhancements to extend the tunables
+ * add a hdr to this structure, so that the version can be set
+ * and checked for backwards compatibility. Newer versions of LNet
+ * can still work with older versions of lnetctl. The restriction is
+ * that the structure can be added to and not removed from in order
+ * to not invalidate older lnetctl utilities. Moreover, the order of
+ * fields must remain the same, and new fields appended to the structure
+ *
+ * That said all existing LND tunables will be added in this structure
+ * to avoid future changes.
+ */
struct lnet_ioctl_config_lnd_cmn_tunables {
__u32 lct_version;
__s32 lct_peer_timeout;
/* # different router buffer pools */
#define LNET_NRBPOOLS (LNET_LARGE_BUF_IDX + 1)
+enum lnet_dbg_task {
+ LNET_DBG_INCR_DLC_SEQ = 0
+};
+
struct lnet_ioctl_pool_cfg {
struct {
__u32 pl_npages;
char cfg_bulk[0];
};
+/*
+ * lnet_ioctl_config_ni
+ * This structure describes an NI configuration. There are multiple components
+ * when configuring an NI: Net, Interfaces, CPT list and LND tunables
+ * A network is passed as a string to the DLC and translated using
+ * libcfs_str2net()
+ * An interface is the name of the system configured interface
+ * (ex eth0, ib1)
+ * CPT is the list of CPTS LND tunables are passed in the lic_bulk area
+ */
+struct lnet_ioctl_config_ni {
+ struct libcfs_ioctl_hdr lic_cfg_hdr;
+ lnet_nid_t lic_nid;
+ char lic_ni_intf[LNET_MAX_INTERFACES][LNET_MAX_STR_LEN];
+ char lic_legacy_ip2nets[LNET_MAX_STR_LEN];
+ __u32 lic_cpts[LNET_MAX_SHOW_NUM_CPT];
+ __u32 lic_ncpts;
+ __u32 lic_status;
+ __u32 lic_tcp_bonding;
+ __u32 lic_idx;
+ char lic_bulk[0];
+};
+
struct lnet_peer_ni_credit_info {
char cr_aliveness[LNET_MAX_STR_LEN];
__u32 cr_refcount;
} pr_lnd_u;
};
+struct lnet_dbg_task_info {
+ /*
+ * TODO: a union can be added if the task requires more
+ * information from user space to be carried out in kernel space.
+ */
+};
+
+/*
+ * This structure is intended to allow execution of debugging tasks. This
+ * is not intended to be backwards compatible. Extra tasks can be added in
+ * the future
+ */
+struct lnet_ioctl_dbg {
+ struct libcfs_ioctl_hdr dbg_hdr;
+ enum lnet_dbg_task dbg_task;
+ char dbg_bulk[0];
+};
+
struct lnet_ioctl_peer_cfg {
struct libcfs_ioctl_hdr prcfg_hdr;
lnet_nid_t prcfg_key_nid;
struct lnet_ni *
lnet_ni_alloc(struct lnet_net *net, struct cfs_expr_list *el,
char *iface);
+struct lnet_ni *
+lnet_ni_alloc_w_cpt_array(struct lnet_net *net, __u32 *cpts, __u32 ncpts,
+ char *iface);
static inline int
lnet_nid2peerhash(lnet_nid_t nid)
extern lnet_ni_t *lnet_nid2ni_locked(lnet_nid_t nid, int cpt);
extern lnet_ni_t *lnet_nid2ni_addref(lnet_nid_t nid);
extern lnet_ni_t *lnet_net2ni_locked(__u32 net, int cpt);
-extern lnet_ni_t *lnet_net2ni(__u32 net);
+extern lnet_ni_t *lnet_net2ni_addref(__u32 net);
bool lnet_is_ni_healthy_locked(struct lnet_ni *ni);
struct lnet_net *lnet_get_net_locked(__u32 net_id);
void lnet_rtrpools_disable(void);
void lnet_rtrpools_free(int keep_pools);
lnet_remotenet_t *lnet_find_rnet_locked(__u32 net);
-int lnet_dyn_add_ni(lnet_pid_t requested_pid,
- struct lnet_ioctl_config_data *conf);
-int lnet_dyn_del_ni(__u32 net);
+int lnet_dyn_add_net(struct lnet_ioctl_config_data *conf);
+int lnet_dyn_del_net(__u32 net);
+int lnet_dyn_add_ni(struct lnet_ioctl_config_ni *conf);
+int lnet_dyn_del_ni(struct lnet_ioctl_config_ni *conf);
int lnet_clear_lazy_portal(struct lnet_ni *ni, int portal, char *reason);
struct lnet_net *lnet_get_net_locked(__u32 net_id);
struct lnet_peer **peer);
int lnet_nid2peerni_locked(struct lnet_peer_ni **lpp, lnet_nid_t nid, int cpt);
struct lnet_peer_ni *lnet_find_peer_ni_locked(lnet_nid_t nid);
+void lnet_peer_net_added(struct lnet_net *net);
void lnet_peer_tables_cleanup(lnet_ni_t *ni);
void lnet_peer_uninit(void);
int lnet_peer_tables_create(void);
int rc;
int i;
- LASSERT(ncpts > 0 && ncpts <= cfs_cpt_number(lnet_cpt_table()));
+ if (ncpts > 0 && ncpts > cfs_cpt_number(lnet_cpt_table()))
+ return -EINVAL;
for (i = 0; i < ncpts; i++) {
struct ksock_sched_info *info;
}
lnet_ni_t *
-lnet_net2ni(__u32 net)
+lnet_net2ni_addref(__u32 net)
{
lnet_ni_t *ni;
lnet_net_lock(0);
ni = lnet_net2ni_locked(net, 0);
+ if (ni)
+ lnet_ni_addref_locked(ni, 0);
lnet_net_unlock(0);
return ni;
}
-EXPORT_SYMBOL(lnet_net2ni);
+EXPORT_SYMBOL(lnet_net2ni_addref);
struct lnet_net *
lnet_get_net_locked(__u32 net_id)
}
static inline int
+lnet_get_net_ni_count_pre(struct lnet_net *net)
+{
+ struct lnet_ni *ni;
+ int count = 0;
+
+ list_for_each_entry(ni, &net->net_ni_added, ni_netlist)
+ count++;
+
+ return count;
+}
+
+static inline int
lnet_get_ni_count(void)
{
struct lnet_ni *ni;
}
EXPORT_SYMBOL(LNetNIFini);
+
+static int lnet_handle_dbg_task(struct lnet_ioctl_dbg *dbg,
+ struct lnet_dbg_task_info *dbg_info)
+{
+ switch (dbg->dbg_task) {
+ case LNET_DBG_INCR_DLC_SEQ:
+ lnet_incr_dlc_seq();
+ }
+
+ return 0;
+}
+/**
+ * Grabs the ni data from the ni structure and fills the out
+ * parameters
+ *
+ * \param[in] ni network interface structure
+ * \param[out] cfg_ni NI config information
+ * \param[out] tun network and LND tunables
+ */
+static void
+lnet_fill_ni_info(struct lnet_ni *ni, struct lnet_ioctl_config_ni *cfg_ni,
+ struct lnet_ioctl_config_lnd_tunables *tun,
+ __u32 tun_size)
+{
+ size_t min_size = 0;
+ int i;
+
+ if (!ni || !cfg_ni || !tun)
+ return;
+
+ if (ni->ni_interfaces[0] != NULL) {
+ for (i = 0; i < ARRAY_SIZE(ni->ni_interfaces); i++) {
+ if (ni->ni_interfaces[i] != NULL) {
+ strncpy(cfg_ni->lic_ni_intf[i],
+ ni->ni_interfaces[i],
+ sizeof(cfg_ni->lic_ni_intf[i]));
+ }
+ }
+ }
+
+ cfg_ni->lic_nid = ni->ni_nid;
+ cfg_ni->lic_status = ni->ni_status->ns_status;
+ cfg_ni->lic_tcp_bonding = use_tcp_bonding;
+
+ memcpy(&tun->lt_cmn, &ni->ni_net->net_tunables, sizeof(tun->lt_cmn));
+
+ /*
+ * tun->lt_tun will always be present, but in order to be
+ * backwards compatible, we need to deal with the cases when
+ * tun->lt_tun is smaller than what the kernel has, because it
+ * comes from an older version of a userspace program, then we'll
+ * need to copy as much information as we have available space.
+ */
+ min_size = tun_size - sizeof(tun->lt_cmn);
+ memcpy(&tun->lt_tun, &ni->ni_lnd_tunables, min_size);
+
+ /* copy over the cpts */
+ if (ni->ni_ncpts == LNET_CPT_NUMBER &&
+ ni->ni_cpts == NULL) {
+ for (i = 0; i < ni->ni_ncpts; i++)
+ cfg_ni->lic_cpts[i] = i;
+ } else {
+ for (i = 0;
+ ni->ni_cpts != NULL && i < ni->ni_ncpts &&
+ i < LNET_MAX_SHOW_NUM_CPT;
+ i++)
+ cfg_ni->lic_cpts[i] = ni->ni_cpts[i];
+ }
+ cfg_ni->lic_ncpts = ni->ni_ncpts;
+}
+
/**
+ * NOTE: This is a legacy function left in the code to be backwards
+ * compatible with older userspace programs. It should eventually be
+ * removed.
+ *
* Grabs the ni data from the ni structure and fills the out
* parameters
*
* \param[in] ni network interface structure
- * \param[out] cpt_count the number of cpts the ni is on
- * \param[out] nid Network Interface ID
- * \param[out] peer_timeout NI peer timeout
- * \param[out] peer_tx_crdits NI peer transmit credits
- * \param[out] peer_rtr_credits NI peer router credits
- * \param[out] max_tx_credits NI max transmit credit
- * \param[out] net_config Network configuration
+ * \param[out] config config information
*/
static void
-lnet_fill_ni_info(struct lnet_ni *ni, struct lnet_ioctl_config_data *config)
+lnet_fill_ni_info_legacy(struct lnet_ni *ni,
+ struct lnet_ioctl_config_data *config)
{
struct lnet_ioctl_net_config *net_config;
struct lnet_ioctl_config_lnd_tunables *lnd_cfg = NULL;
if (ni != NULL) {
rc = 0;
lnet_ni_lock(ni);
- lnet_fill_ni_info(ni, config);
+ lnet_fill_ni_info_legacy(ni, config);
lnet_ni_unlock(ni);
}
}
int
-lnet_dyn_add_ni(lnet_pid_t requested_pid, struct lnet_ioctl_config_data *conf)
+lnet_get_ni_config(struct lnet_ioctl_config_ni *cfg_ni,
+ struct lnet_ioctl_config_lnd_tunables *tun,
+ __u32 tun_size)
{
- char *nets = conf->cfg_config_u.cfg_net.net_intf;
- struct lnet_ping_info *pinfo;
- lnet_handle_md_t md_handle;
- struct lnet_net *net;
- struct list_head net_head;
- int rc;
- lnet_remotenet_t *rnet;
- int net_ni_count;
- int num_acceptor_nets;
- __u32 net_type;
- struct lnet_ioctl_config_lnd_tunables *lnd_tunables = NULL;
-
- INIT_LIST_HEAD(&net_head);
+ struct lnet_ni *ni;
+ int cpt;
+ int rc = -ENOENT;
- if (conf && conf->cfg_hdr.ioc_len > sizeof(*conf))
- lnd_tunables = (struct lnet_ioctl_config_lnd_tunables *)conf->cfg_bulk;
+ if (!cfg_ni || !tun)
+ return -EINVAL;
- /* Create a net/ni structures for the network string */
- rc = lnet_parse_networks(&net_head, nets, use_tcp_bonding);
- if (rc <= 0)
- return rc == 0 ? -EINVAL : rc;
+ cpt = lnet_net_lock_current();
- mutex_lock(&the_lnet.ln_api_mutex);
+ ni = lnet_get_ni_idx_locked(cfg_ni->lic_idx);
- if (rc > 1) {
- rc = -EINVAL; /* only add one network per call */
- goto failed0;
+ if (ni) {
+ rc = 0;
+ lnet_ni_lock(ni);
+ lnet_fill_ni_info(ni, cfg_ni, tun, tun_size);
+ lnet_ni_unlock(ni);
}
- net = list_entry(net_head.next, struct lnet_net, net_list);
+ lnet_net_unlock(cpt);
+ return rc;
+}
+
+static int lnet_add_net_common(struct lnet_net *net,
+ struct lnet_ioctl_config_lnd_tunables *tun)
+{
+ struct lnet_net *netl = NULL;
+ __u32 net_id;
+ lnet_ping_info_t *pinfo;
+ lnet_handle_md_t md_handle;
+ int rc;
+ lnet_remotenet_t *rnet;
+ int net_ni_count;
+ int num_acceptor_nets;
lnet_net_lock(LNET_LOCK_EX);
rnet = lnet_find_rnet_locked(net->net_id);
lnet_net_unlock(LNET_LOCK_EX);
- /* make sure that the net added doesn't invalidate the current
- * configuration LNet is keeping */
- if (rnet != NULL) {
+ /*
+ * make sure that the net added doesn't invalidate the current
+ * configuration LNet is keeping
+ */
+ if (rnet) {
CERROR("Adding net %s will invalidate routing configuration\n",
- nets);
+ libcfs_net2str(net->net_id));
rc = -EUSERS;
- goto failed0;
+ goto failed1;
}
/*
* we should allocate enough slots to accomodate the number of NIs
* which will be added.
*
- * We can use lnet_get_net_ni_count_locked() since the net is not
- * on a public list yet, so locking is not a problem
+ * since ni hasn't been configured yet, use
+ * lnet_get_net_ni_count_pre() which checks the net_ni_added list
*/
- net_ni_count = lnet_get_net_ni_count_locked(net);
+ net_ni_count = lnet_get_net_ni_count_pre(net);
rc = lnet_ping_info_setup(&pinfo, &md_handle,
net_ni_count + lnet_get_ni_count(),
false);
- if (rc != 0)
- goto failed0;
-
- list_del_init(&net->net_list);
+ if (rc < 0)
+ goto failed1;
- if (lnd_tunables)
+ if (tun)
memcpy(&net->net_tunables,
- &lnd_tunables->lt_cmn, sizeof(lnd_tunables->lt_cmn));
+ &tun->lt_cmn, sizeof(net->net_tunables));
+ else
+ memset(&net->net_tunables, -1, sizeof(net->net_tunables));
/*
* before starting this network get a count of the current TCP
*/
num_acceptor_nets = lnet_count_acceptor_nets();
- /*
- * lnd_startup_lndnet() can deallocate 'net' even if it it returns
- * success, because we endded up adding interfaces to an existing
- * network. So grab the net_type now
- */
- net_type = LNET_NETTYP(net->net_id);
+ net_id = net->net_id;
rc = lnet_startup_lndnet(net,
- (lnd_tunables) ? &lnd_tunables->lt_tun : NULL);
+ (tun) ? &tun->lt_tun : NULL);
if (rc < 0)
- goto failed1;
+ goto failed;
+
+ lnet_net_lock(LNET_LOCK_EX);
+ netl = lnet_get_net_locked(net_id);
+ lnet_net_unlock(LNET_LOCK_EX);
+
+ LASSERT(netl);
/*
* Start the acceptor thread if this is the first network
* being added that requires the thread.
*/
- if (net_type == SOCKLND && num_acceptor_nets == 0)
+ if (netl->net_lnd->lnd_accept &&
+ num_acceptor_nets == 0)
{
rc = lnet_acceptor_start();
if (rc < 0) {
/* shutdown the net that we just started */
CERROR("Failed to start up acceptor thread\n");
- /*
- * Note that if we needed to start the acceptor
- * thread, then 'net' must have been the first TCP
- * network, therefore was unique, and therefore
- * wasn't deallocated by lnet_startup_lndnet()
- */
lnet_shutdown_lndnet(net);
- goto failed1;
+ goto failed;
}
}
+ lnet_net_lock(LNET_LOCK_EX);
+ lnet_peer_net_added(netl);
+ lnet_net_unlock(LNET_LOCK_EX);
+
lnet_ping_target_update(pinfo, md_handle);
- mutex_unlock(&the_lnet.ln_api_mutex);
return 0;
-failed1:
+failed:
lnet_ping_md_unlink(pinfo, &md_handle);
lnet_ping_info_free(pinfo);
-failed0:
+failed1:
+ lnet_net_free(net);
+ return rc;
+}
+
+static int lnet_handle_legacy_ip2nets(char *ip2nets,
+ struct lnet_ioctl_config_lnd_tunables *tun)
+{
+ struct lnet_net *net;
+ char *nets;
+ int rc;
+ struct list_head net_head;
+
+ INIT_LIST_HEAD(&net_head);
+
+ rc = lnet_parse_ip2nets(&nets, ip2nets);
+ if (rc < 0)
+ return rc;
+
+ rc = lnet_parse_networks(&net_head, nets, use_tcp_bonding);
+ if (rc < 0)
+ return rc;
+
+ mutex_lock(&the_lnet.ln_api_mutex);
+ while (!list_empty(&net_head)) {
+ net = list_entry(net_head.next, struct lnet_net, net_list);
+ list_del_init(&net->net_list);
+ rc = lnet_add_net_common(net, tun);
+ if (rc < 0)
+ goto out;
+ }
+
+out:
+ mutex_unlock(&the_lnet.ln_api_mutex);
+
+ while (!list_empty(&net_head)) {
+ net = list_entry(net_head.next, struct lnet_net, net_list);
+ list_del_init(&net->net_list);
+ lnet_net_free(net);
+ }
+ return rc;
+}
+
+int lnet_dyn_add_ni(struct lnet_ioctl_config_ni *conf)
+{
+ struct lnet_net *net;
+ struct lnet_ni *ni;
+ struct lnet_ioctl_config_lnd_tunables *tun = NULL;
+ int rc;
+ __u32 net_id;
+
+ /* get the tunables if they are available */
+ if (conf->lic_cfg_hdr.ioc_len >=
+ sizeof(*conf) + sizeof(*tun))
+ tun = (struct lnet_ioctl_config_lnd_tunables *)
+ conf->lic_bulk;
+
+ /* handle legacy ip2nets from DLC */
+ if (conf->lic_legacy_ip2nets[0] != '\0')
+ return lnet_handle_legacy_ip2nets(conf->lic_legacy_ip2nets,
+ tun);
+
+ net_id = LNET_NIDNET(conf->lic_nid);
+
+ net = lnet_net_alloc(net_id, NULL);
+ if (!net)
+ return -ENOMEM;
+
+ ni = lnet_ni_alloc_w_cpt_array(net, conf->lic_cpts, conf->lic_ncpts,
+ conf->lic_ni_intf[0]);
+ if (!ni)
+ return -ENOMEM;
+
+ mutex_lock(&the_lnet.ln_api_mutex);
+
+ rc = lnet_add_net_common(net, tun);
+
+ mutex_unlock(&the_lnet.ln_api_mutex);
+
+ return rc;
+}
+
+int lnet_dyn_del_ni(struct lnet_ioctl_config_ni *conf)
+{
+ struct lnet_net *net;
+ struct lnet_ni *ni;
+ __u32 net_id = LNET_NIDNET(conf->lic_nid);
+ lnet_ping_info_t *pinfo;
+ lnet_handle_md_t md_handle;
+ int rc;
+ int net_count;
+ __u32 addr;
+
+ /* don't allow userspace to shutdown the LOLND */
+ if (LNET_NETTYP(net_id) == LOLND)
+ return -EINVAL;
+
+ mutex_lock(&the_lnet.ln_api_mutex);
+
+ lnet_net_lock(0);
+
+ net = lnet_get_net_locked(net_id);
+ if (!net) {
+ CERROR("net %s not found\n",
+ libcfs_net2str(net_id));
+ rc = -ENOENT;
+ goto net_unlock;
+ }
+
+ addr = LNET_NIDADDR(conf->lic_nid);
+ if (addr == 0) {
+ /* remove the entire net */
+ net_count = lnet_get_net_ni_count_locked(net);
+
+ lnet_net_unlock(0);
+
+ /* create and link a new ping info, before removing the old one */
+ rc = lnet_ping_info_setup(&pinfo, &md_handle,
+ lnet_get_ni_count() - net_count,
+ false);
+ if (rc != 0)
+ goto out;
+
+ lnet_shutdown_lndnet(net);
+
+ if (lnet_count_acceptor_nets() == 0)
+ lnet_acceptor_stop();
+
+ lnet_ping_target_update(pinfo, md_handle);
+
+ goto out;
+ }
+
+ ni = lnet_nid2ni_locked(conf->lic_nid, 0);
+ if (!ni) {
+ CERROR("nid %s not found \n",
+ libcfs_nid2str(conf->lic_nid));
+ rc = -ENOENT;
+ goto net_unlock;
+ }
+
+ net_count = lnet_get_net_ni_count_locked(net);
+
+ lnet_net_unlock(0);
+
+ /* create and link a new ping info, before removing the old one */
+ rc = lnet_ping_info_setup(&pinfo, &md_handle,
+ lnet_get_ni_count() - 1, false);
+ if (rc != 0)
+ goto out;
+
+ lnet_shutdown_lndni(ni);
+
+ if (lnet_count_acceptor_nets() == 0)
+ lnet_acceptor_stop();
+
+ lnet_ping_target_update(pinfo, md_handle);
+
+ /* check if the net is empty and remove it if it is */
+ if (net_count == 1)
+ lnet_shutdown_lndnet(net);
+
+ goto out;
+
+net_unlock:
+ lnet_net_unlock(0);
+out:
+ mutex_unlock(&the_lnet.ln_api_mutex);
+
+ return rc;
+}
+
+/*
+ * lnet_dyn_add_net and lnet_dyn_del_net are now deprecated.
+ * They are only expected to be called for unique networks.
+ * That can be as a result of older DLC library
+ * calls. Multi-Rail DLC and beyond no longer uses these APIs.
+ */
+int
+lnet_dyn_add_net(struct lnet_ioctl_config_data *conf)
+{
+ struct lnet_net *net;
+ struct list_head net_head;
+ int rc;
+ struct lnet_ioctl_config_lnd_tunables tun;
+ char *nets = conf->cfg_config_u.cfg_net.net_intf;
+
+ INIT_LIST_HEAD(&net_head);
+
+ /* Create a net/ni structures for the network string */
+ rc = lnet_parse_networks(&net_head, nets, use_tcp_bonding);
+ if (rc <= 0)
+ return rc == 0 ? -EINVAL : rc;
+
+ mutex_lock(&the_lnet.ln_api_mutex);
+
+ if (rc > 1) {
+ rc = -EINVAL; /* only add one network per call */
+ goto failed;
+ }
+
+ net = list_entry(net_head.next, struct lnet_net, net_list);
+ list_del_init(&net->net_list);
+
+ LASSERT(lnet_net_unique(net->net_id, &the_lnet.ln_nets, NULL));
+
+ memset(&tun, sizeof(tun), 0);
+
+ tun.lt_cmn.lct_peer_timeout =
+ conf->cfg_config_u.cfg_net.net_peer_timeout;
+ tun.lt_cmn.lct_peer_tx_credits =
+ conf->cfg_config_u.cfg_net.net_peer_tx_credits;
+ tun.lt_cmn.lct_peer_rtr_credits =
+ conf->cfg_config_u.cfg_net.net_peer_rtr_credits;
+ tun.lt_cmn.lct_max_tx_credits =
+ conf->cfg_config_u.cfg_net.net_max_tx_credits;
+
+ rc = lnet_add_net_common(net, &tun);
+ if (rc != 0)
+ goto failed;
+
+ return 0;
+
+failed:
mutex_unlock(&the_lnet.ln_api_mutex);
while (!list_empty(&net_head)) {
net = list_entry(net_head.next, struct lnet_net, net_list);
}
int
-lnet_dyn_del_ni(__u32 net_id)
+lnet_dyn_del_net(__u32 net_id)
{
struct lnet_net *net;
struct lnet_ping_info *pinfo;
&config->cfg_config_u.cfg_route.
rtr_priority);
+ case IOC_LIBCFS_GET_LOCAL_NI: {
+ struct lnet_ioctl_config_ni *cfg_ni;
+ struct lnet_ioctl_config_lnd_tunables *tun = NULL;
+ __u32 tun_size;
+
+ cfg_ni = arg;
+ /* get the tunables if they are available */
+ if (cfg_ni->lic_cfg_hdr.ioc_len <
+ sizeof(*cfg_ni) + sizeof(*tun))
+ return -EINVAL;
+
+ tun = (struct lnet_ioctl_config_lnd_tunables *)
+ cfg_ni->lic_bulk;
+
+ tun_size = cfg_ni->lic_cfg_hdr.ioc_len - sizeof(*cfg_ni);
+
+ return lnet_get_ni_config(cfg_ni, tun, tun_size);
+ }
+
case IOC_LIBCFS_GET_NET: {
size_t total = sizeof(*config) +
sizeof(struct lnet_ioctl_net_config);
data->ioc_count = rc;
return 0;
}
+
+ case IOC_LIBCFS_DBG: {
+ struct lnet_ioctl_dbg *dbg = arg;
+ struct lnet_dbg_task_info *dbg_info;
+ size_t total = sizeof(*dbg) + sizeof(*dbg_info);
+
+ if (dbg->dbg_hdr.ioc_len < total)
+ return -EINVAL;
+
+ dbg_info = (struct lnet_dbg_task_info*) dbg->dbg_bulk;
+
+ return lnet_handle_dbg_task(dbg, dbg_info);
+ }
+
default:
- ni = lnet_net2ni(data->ioc_net);
+ ni = lnet_net2ni_addref(data->ioc_net);
if (ni == NULL)
return -EINVAL;
else
rc = ni->ni_net->net_lnd->lnd_ctl(ni, cmd, arg);
+ lnet_ni_decref(ni);
return rc;
}
/* not reached */
{
struct lnet_net *net_l;
+ if (!netlist)
+ return true;
+
list_for_each_entry(net_l, netlist, net_list) {
if (net_l->net_id == net_id) {
if (net != NULL)
if (net->net_cpts == NULL)
return -ENOMEM;
memcpy(net->net_cpts, cpts, ncpts);
+ net->net_ncpts = ncpts;
return 0;
}
net->net_tunables.lct_peer_tx_credits = -1;
net->net_tunables.lct_peer_rtr_credits = -1;
- list_add_tail(&net->net_list, net_list);
+ if (net_list)
+ list_add_tail(&net->net_list, net_list);
return net;
}
return 0;
}
-/* allocate and add to the provided network */
-lnet_ni_t *
-lnet_ni_alloc(struct lnet_net *net, struct cfs_expr_list *el, char *iface)
+static struct lnet_ni *
+lnet_ni_alloc_common(struct lnet_net *net, char *iface)
{
struct lnet_tx_queue *tq;
struct lnet_ni *ni;
- int rc;
int i;
if (iface != NULL)
cfs_percpt_for_each(tq, i, ni->ni_tx_queues)
INIT_LIST_HEAD(&tq->tq_delayed);
- if (el == NULL) {
+ ni->ni_net = net;
+ /* LND will fill in the address part of the NID */
+ ni->ni_nid = LNET_MKNID(net->net_id, 0);
+
+ /* Store net namespace in which current ni is being created */
+ if (current->nsproxy->net_ns != NULL)
+ ni->ni_net_ns = get_net(current->nsproxy->net_ns);
+ else
+ ni->ni_net_ns = NULL;
+
+ ni->ni_last_alive = ktime_get_real_seconds();
+ ni->ni_state = LNET_NI_STATE_INIT;
+ list_add_tail(&ni->ni_netlist, &net->net_ni_added);
+
+ /*
+ * if an interface name is provided then make sure to add in that
+ * interface name in NI
+ */
+ if (iface)
+ if (lnet_ni_add_interface(ni, iface) != 0)
+ goto failed;
+
+ return ni;
+failed:
+ lnet_ni_free(ni);
+ return NULL;
+}
+
+/* allocate and add to the provided network */
+struct lnet_ni *
+lnet_ni_alloc(struct lnet_net *net, struct cfs_expr_list *el, char *iface)
+{
+ struct lnet_ni *ni;
+ int rc;
+
+ ni = lnet_ni_alloc_common(net, iface);
+ if (!ni)
+ return NULL;
+
+ if (!el) {
ni->ni_cpts = NULL;
ni->ni_ncpts = LNET_CPT_NUMBER;
} else {
ni->ni_ncpts = rc;
}
- ni->ni_net = net;
- /* LND will fill in the address part of the NID */
- ni->ni_nid = LNET_MKNID(net->net_id, 0);
-
- /* Store net namespace in which current ni is being created */
- if (current->nsproxy->net_ns != NULL)
- ni->ni_net_ns = get_net(current->nsproxy->net_ns);
- else
- ni->ni_net_ns = NULL;
-
- ni->ni_last_alive = ktime_get_real_seconds();
- ni->ni_state = LNET_NI_STATE_INIT;
rc = lnet_net_append_cpts(ni->ni_cpts, ni->ni_ncpts, net);
if (rc != 0)
goto failed;
- list_add_tail(&ni->ni_netlist, &net->net_ni_added);
- /* if an interface name is provided then make sure to add in that
- * interface name in NI */
- if (iface != NULL)
- if (lnet_ni_add_interface(ni, iface) != 0)
+ return ni;
+failed:
+ lnet_ni_free(ni);
+ return NULL;
+}
+
+struct lnet_ni *
+lnet_ni_alloc_w_cpt_array(struct lnet_net *net, __u32 *cpts, __u32 ncpts,
+ char *iface)
+{
+ struct lnet_ni *ni;
+ int rc;
+
+ ni = lnet_ni_alloc_common(net, iface);
+ if (!ni)
+ return NULL;
+
+ if (ncpts == 0) {
+ ni->ni_cpts = NULL;
+ ni->ni_ncpts = LNET_CPT_NUMBER;
+ } else {
+ size_t array_size = ncpts * sizeof(ni->ni_cpts[0]);
+ LIBCFS_ALLOC(ni->ni_cpts, array_size);
+ if (ni->ni_cpts == NULL)
goto failed;
+ memcpy(ni->ni_cpts, cpts, array_size);
+ ni->ni_ncpts = ncpts;
+ }
+
+ rc = lnet_net_append_cpts(ni->ni_cpts, ni->ni_ncpts, net);
+ if (rc != 0)
+ goto failed;
return ni;
failed:
}
static int
-lnet_dyn_configure(struct libcfs_ioctl_hdr *hdr)
+lnet_dyn_configure_net(struct libcfs_ioctl_hdr *hdr)
{
struct lnet_ioctl_config_data *conf =
(struct lnet_ioctl_config_data *)hdr;
return -EINVAL;
mutex_lock(&lnet_config_mutex);
- if (!the_lnet.ln_niinit_self) {
+ if (the_lnet.ln_niinit_self)
+ rc = lnet_dyn_add_net(conf);
+ else
rc = -EINVAL;
- goto out_unlock;
- }
- rc = lnet_dyn_add_ni(LNET_PID_LUSTRE, conf);
-out_unlock:
mutex_unlock(&lnet_config_mutex);
return rc;
}
static int
-lnet_dyn_unconfigure(struct libcfs_ioctl_hdr *hdr)
+lnet_dyn_unconfigure_net(struct libcfs_ioctl_hdr *hdr)
{
struct lnet_ioctl_config_data *conf =
(struct lnet_ioctl_config_data *) hdr;
return -EINVAL;
mutex_lock(&lnet_config_mutex);
- if (!the_lnet.ln_niinit_self) {
+ if (the_lnet.ln_niinit_self)
+ rc = lnet_dyn_del_net(conf->cfg_net);
+ else
+ rc = -EINVAL;
+ mutex_unlock(&lnet_config_mutex);
+
+ return rc;
+}
+
+static int
+lnet_dyn_configure_ni(struct libcfs_ioctl_hdr *hdr)
+{
+ struct lnet_ioctl_config_ni *conf =
+ (struct lnet_ioctl_config_ni *)hdr;
+ int rc;
+
+ if (conf->lic_cfg_hdr.ioc_len < sizeof(*conf))
+ return -EINVAL;
+
+ mutex_lock(&lnet_config_mutex);
+ if (the_lnet.ln_niinit_self)
+ rc = lnet_dyn_add_ni(conf);
+ else
+ rc = -EINVAL;
+ mutex_unlock(&lnet_config_mutex);
+
+ return rc;
+}
+
+static int
+lnet_dyn_unconfigure_ni(struct libcfs_ioctl_hdr *hdr)
+{
+ struct lnet_ioctl_config_ni *conf =
+ (struct lnet_ioctl_config_ni *) hdr;
+ int rc;
+
+ if (conf->lic_cfg_hdr.ioc_len < sizeof(*conf))
+ return -EINVAL;
+
+ mutex_lock(&lnet_config_mutex);
+ if (the_lnet.ln_niinit_self)
+ rc = lnet_dyn_del_ni(conf);
+ else
rc = -EINVAL;
- goto out_unlock;
- }
- rc = lnet_dyn_del_ni(conf->cfg_net);
-out_unlock:
mutex_unlock(&lnet_config_mutex);
return rc;
return lnet_unconfigure();
case IOC_LIBCFS_ADD_NET:
- return lnet_dyn_configure(hdr);
+ return lnet_dyn_configure_net(hdr);
case IOC_LIBCFS_DEL_NET:
- return lnet_dyn_unconfigure(hdr);
+ return lnet_dyn_unconfigure_net(hdr);
+
+ case IOC_LIBCFS_ADD_LOCAL_NI:
+ return lnet_dyn_configure_ni(hdr);
+
+ case IOC_LIBCFS_DEL_LOCAL_NI:
+ return lnet_dyn_unconfigure_ni(hdr);
default:
/* Passing LNET_PID_ANY only gives me a ref if the net is up
}
}
+void
+lnet_peer_net_added(struct lnet_net *net)
+{
+ struct lnet_peer_ni *lpni, *tmp;
+
+ list_for_each_entry_safe(lpni, tmp, &the_lnet.ln_remote_peer_ni_list,
+ lpni_on_remote_peer_ni_list) {
+
+ if (LNET_NIDNET(lpni->lpni_nid) == net->net_id) {
+ lpni->lpni_net = net;
+ lpni->lpni_txcredits =
+ lpni->lpni_mintxcredits =
+ lpni->lpni_net->net_tunables.lct_peer_tx_credits;
+ lpni->lpni_rtrcredits =
+ lpni->lpni_minrtrcredits =
+ lnet_peer_buffer_credits(lpni->lpni_net);
+
+ lnet_peer_remove_from_remote_list(lpni);
+ }
+ }
+}
+
static void
lnet_peer_tables_destroy(void)
{
lpni->lpni_net = lnet_get_net_locked(LNET_NIDNET(lpni->lpni_nid));
if (lpni->lpni_net != NULL) {
lpni->lpni_txcredits =
- lpni->lpni_mintxcredits = lpni->lpni_net->net_peertxcredits;
+ lpni->lpni_mintxcredits =
+ lpni->lpni_net->net_tunables.lct_peer_tx_credits;
lpni->lpni_rtrcredits =
lpni->lpni_minrtrcredits = lnet_peer_buffer_credits(lpni->lpni_net);
} else {
peer_ni_info->cr_refcount = atomic_read(&lpni->lpni_refcount);
peer_ni_info->cr_ni_peer_tx_credits = (lpni->lpni_net != NULL) ?
- lpni->lpni_net->net_peertxcredits : 0;
+ lpni->lpni_net->net_tunables.lct_peer_tx_credits : 0;
peer_ni_info->cr_peer_tx_credits = lpni->lpni_txcredits;
peer_ni_info->cr_peer_rtr_credits = lpni->lpni_rtrcredits;
peer_ni_info->cr_peer_min_rtr_credits = lpni->lpni_mintxcredits;
[YAML_SCALAR_TOKEN] = yaml_scalar,
};
+/* dispatch table */
+static char *token_type_string[] = {
+ [YAML_NO_TOKEN] = "YAML_NO_TOKEN",
+ [YAML_STREAM_START_TOKEN] = "YAML_STREAM_START_TOKEN",
+ [YAML_STREAM_END_TOKEN] = "YAML_STREAM_END_TOKEN",
+ [YAML_VERSION_DIRECTIVE_TOKEN] = "YAML_VERSION_DIRECTIVE_TOKEN",
+ [YAML_TAG_DIRECTIVE_TOKEN] = "YAML_TAG_DIRECTIVE_TOKEN",
+ [YAML_DOCUMENT_START_TOKEN] = "YAML_DOCUMENT_START_TOKEN",
+ [YAML_DOCUMENT_END_TOKEN] = "YAML_DOCUMENT_END_TOKEN",
+ [YAML_BLOCK_SEQUENCE_START_TOKEN] = "YAML_BLOCK_SEQUENCE_START_TOKEN",
+ [YAML_BLOCK_MAPPING_START_TOKEN] = "YAML_BLOCK_MAPPING_START_TOKEN",
+ [YAML_BLOCK_END_TOKEN] = "YAML_BLOCK_END_TOKEN",
+ [YAML_FLOW_SEQUENCE_START_TOKEN] = "YAML_FLOW_SEQUENCE_START_TOKEN",
+ [YAML_FLOW_SEQUENCE_END_TOKEN] = "YAML_FLOW_SEQUENCE_END_TOKEN",
+ [YAML_FLOW_MAPPING_START_TOKEN] = "YAML_FLOW_MAPPING_START_TOKEN",
+ [YAML_FLOW_MAPPING_END_TOKEN] = "YAML_FLOW_MAPPING_END_TOKEN",
+ [YAML_BLOCK_ENTRY_TOKEN] = "YAML_BLOCK_ENTRY_TOKEN",
+ [YAML_FLOW_ENTRY_TOKEN] = "YAML_FLOW_ENTRY_TOKEN",
+ [YAML_KEY_TOKEN] = "YAML_KEY_TOKEN",
+ [YAML_VALUE_TOKEN] = "YAML_VALUE_TOKEN",
+ [YAML_ALIAS_TOKEN] = "YAML_ALIAS_TOKEN",
+ [YAML_ANCHOR_TOKEN] = "YAML_ANCHOR_TOKEN",
+ [YAML_TAG_TOKEN] = "YAML_TAG_TOKEN",
+ [YAML_SCALAR_TOKEN] = "YAML_SCALAR_TOKEN",
+};
+
static void cYAML_ll_free(struct list_head *ll)
{
struct cYAML_ll *node, *tmp;
struct cYAML *cYAML_build_tree(char *yaml_file,
const char *yaml_blk,
size_t yaml_blk_size,
- struct cYAML **err_rc)
+ struct cYAML **err_rc,
+ bool debug)
{
yaml_parser_t parser;
yaml_token_t token;
*/
yaml_parser_scan(&parser, &token);
+ if (debug)
+ fprintf(stderr, "token.type = %s: %s\n",
+ token_type_string[token.type],
+ (token.type == YAML_SCALAR_TOKEN) ?
+ (char*)token.data.scalar.value : "");
rc = dispatch_tbl[token.type](&token, &tree);
if (rc != CYAML_ERROR_NONE) {
snprintf(err_str, sizeof(err_str),
*/
struct cYAML *cYAML_build_tree(char *yaml_file, const char *yaml_blk,
size_t yaml_blk_size,
- struct cYAML **err_str);
+ struct cYAML **err_str, bool debug);
/*
* cYAML_print_tree
liblnetconfig_lnd.c liblnd.h $(CYAML)
liblnetconfig_la_CPPFLAGS = -D_LARGEFILE64_SOURCE=1 -D_FILE_OFFSET_BITS=64 \
-DLUSTRE_UTILS=1 -I$(top_builddir)/lnet/utils/cyaml
-liblnetconfig_la_LDFLAGS = -L$(top_builddir)/libcfs/libcfs -version-info 1:1:0
+liblnetconfig_la_LDFLAGS = -L$(top_builddir)/libcfs/libcfs -version-info 2:0:0
EXTRA_DIST =
#include "cyaml.h"
int
-lustre_interface_show_net(struct cYAML *interfaces, unsigned int index,
- bool detail, struct lnet_ioctl_config_data *data,
- struct lnet_ioctl_net_config *net_config);
+lustre_net_show_tunables(struct cYAML *tunables,
+ struct lnet_ioctl_config_lnd_cmn_tunables *cmn);
+
+int
+lustre_ni_show_tunables(struct cYAML *lnd_tunables,
+ __u32 net_type,
+ struct lnet_lnd_tunables *lnd);
void
-lustre_interface_parse(struct cYAML *lndparams, const char *dev_name,
- struct lnet_ioctl_config_lnd_tunables *lnd_cfg);
+lustre_yaml_extract_lnd_tunables(struct cYAML *tree,
+ __u32 net_type,
+ struct lnet_lnd_tunables *tun);
#endif /* LIB_LND_CONFIG_API_H */
#include <errno.h>
#include <limits.h>
+#include <byteswap.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
+#include <net/if.h>
#include <libcfs/util/ioctl.h>
#include <lnet/lnetctl.h>
#include <lnet/socklnd.h>
#include "liblnd.h"
+#include <lnet/lnet.h>
+#include <libcfs/libcfs_string.h>
+#include <sys/types.h>
+#include <ifaddrs.h>
#include "liblnetconfig.h"
#include "cyaml.h"
#define ADD_CMD "add"
#define DEL_CMD "del"
#define SHOW_CMD "show"
+#define DBG_CMD "dbg"
+
+/*
+ * lustre_lnet_ip_range_descr
+ * Describes an IP range.
+ * Each octect is an expression
+ */
+struct lustre_lnet_ip_range_descr {
+ struct list_head ipr_entry;
+ struct list_head ipr_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_add_ip_range
+ * Formatting:
+ * given a string of the format:
+ * <expr.expr.expr.expr> parse each expr into
+ * a lustre_lnet_ip_range_descr structure and insert on the list.
+ *
+ * This function is called from
+ * YAML on each ip-range.
+ * As a result of lnetctl command
+ * When building a NID or P2P selection rules
+ */
+int lustre_lnet_add_ip_range(struct list_head *list, char *str_ip_range)
+{
+ struct lustre_lnet_ip_range_descr *ip_range;
+ int rc;
+
+ ip_range = calloc(1, sizeof(*ip_range));
+ if (ip_range == NULL)
+ return LUSTRE_CFG_RC_OUT_OF_MEM;
+
+ INIT_LIST_HEAD(&ip_range->ipr_entry);
+ INIT_LIST_HEAD(&ip_range->ipr_expr);
+
+ rc = cfs_ip_addr_parse(str_ip_range, strlen(str_ip_range),
+ &ip_range->ipr_expr);
+ if (rc != 0)
+ return LUSTRE_CFG_RC_BAD_PARAM;
+
+ list_add_tail(&ip_range->ipr_entry, list);
+
+ return LUSTRE_CFG_RC_NO_ERR;
+}
+
+int lustre_lnet_add_intf_descr(struct list_head *list, char *intf, int len)
+{
+ char *open_sq_bracket = NULL, *close_sq_bracket = NULL,
+ *intf_name;
+ struct lnet_dlc_intf_descr *intf_descr = NULL;
+ int rc;
+ char intf_string[LNET_MAX_STR_LEN];
+
+ if (len >= LNET_MAX_STR_LEN)
+ return LUSTRE_CFG_RC_BAD_PARAM;
+
+ strncpy(intf_string, intf, len);
+ intf_string[len] = '\0';
+
+ intf_descr = calloc(1, sizeof(*intf_descr));
+ if (intf_descr == NULL)
+ return LUSTRE_CFG_RC_OUT_OF_MEM;
+
+ INIT_LIST_HEAD(&intf_descr->intf_on_network);
+
+ intf_name = intf_string;
+ open_sq_bracket = strchr(intf_string, '[');
+ if (open_sq_bracket != NULL) {
+ close_sq_bracket = strchr(intf_string, ']');
+ if (close_sq_bracket == NULL) {
+ free(intf_descr);
+ return LUSTRE_CFG_RC_BAD_PARAM;
+ }
+ rc = cfs_expr_list_parse(open_sq_bracket,
+ strlen(open_sq_bracket), 0, UINT_MAX,
+ &intf_descr->cpt_expr);
+ if (rc < 0) {
+ free(intf_descr);
+ return LUSTRE_CFG_RC_BAD_PARAM;
+ }
+ strncpy(intf_descr->intf_name, intf_name,
+ open_sq_bracket - intf_name);
+ intf_descr->intf_name[open_sq_bracket - intf_name] = '\0';
+ } else {
+ strcpy(intf_descr->intf_name, intf_name);
+ intf_descr->cpt_expr = NULL;
+ }
+
+ list_add_tail(&intf_descr->intf_on_network, list);
+
+ return LUSTRE_CFG_RC_NO_ERR;
+}
+
+void lustre_lnet_init_nw_descr(struct lnet_dlc_network_descr *nw_descr)
+{
+ if (nw_descr != NULL) {
+ INIT_LIST_HEAD(&nw_descr->network_on_rule);
+ INIT_LIST_HEAD(&nw_descr->nw_intflist);
+ }
+}
+
+/*
+ * format expected:
+ * <intf>[<expr>], <intf>[<expr>],..
+ */
+int lustre_lnet_parse_interfaces(char *intf_str,
+ struct lnet_dlc_network_descr *nw_descr)
+{
+ char *open_square;
+ char *close_square;
+ char *comma;
+ char *cur = intf_str, *next = NULL;
+ char *end = intf_str + strlen(intf_str);
+ int rc, len;
+ struct lnet_dlc_intf_descr *intf_descr, *tmp;
+
+ if (nw_descr == NULL)
+ return LUSTRE_CFG_RC_BAD_PARAM;
+
+ while (cur < end) {
+ open_square = strchr(cur, '[');
+ if (open_square != NULL) {
+ close_square = strchr(cur, ']');
+ if (close_square == NULL) {
+ rc = LUSTRE_CFG_RC_BAD_PARAM;
+ goto failed;
+ }
+
+ comma = strchr(cur, ',');
+ if (comma != NULL && comma > close_square) {
+ next = comma + 1;
+ len = next - close_square;
+ } else {
+ len = strlen(cur);
+ next = cur + len;
+ }
+ } else {
+ comma = strchr(cur, ',');
+ if (comma != NULL) {
+ next = comma + 1;
+ len = comma - cur;
+ } else {
+ len = strlen(cur);
+ next = cur + len;
+ }
+ }
+
+ rc = lustre_lnet_add_intf_descr(&nw_descr->nw_intflist, cur, len);
+ if (rc != LUSTRE_CFG_RC_NO_ERR)
+ goto failed;
+
+ cur = next;
+ }
+
+ return LUSTRE_CFG_RC_NO_ERR;
+
+failed:
+ list_for_each_entry_safe(intf_descr, tmp, &nw_descr->nw_intflist,
+ intf_on_network) {
+ if (intf_descr->cpt_expr != NULL)
+ cfs_expr_list_free(intf_descr->cpt_expr);
+ free(intf_descr);
+ }
+
+ return rc;
+}
int lustre_lnet_config_lib_init(void)
{
LNET_DEV_MAJOR, LNET_DEV_MINOR);
}
+void lustre_lnet_config_lib_uninit(void)
+{
+ unregister_ioc_dev(LNET_DEV_ID);
+}
+
int lustre_lnet_config_ni_system(bool up, bool load_ni_from_mod,
int seq_no, struct cYAML **err_rc)
{
return rc;
}
-int lustre_lnet_config_net(char *net, char *intf, char *ip2net,
- int peer_to, int peer_cr, int peer_buf_cr,
- int credits, char *smp, int seq_no,
- struct lnet_ioctl_config_lnd_tunables *lnd_tunables,
- struct cYAML **err_rc)
+static int socket_intf_query(int request, char *intf,
+ struct ifreq *ifr)
{
- struct lnet_ioctl_config_lnd_tunables *lnd = NULL;
- struct lnet_ioctl_config_data *data;
- size_t ioctl_size = sizeof(*data);
- char buf[LNET_MAX_STR_LEN];
+ int rc;
+ int sockfd;
+
+ if (strlen(intf) >= IFNAMSIZ || ifr == NULL)
+ return LUSTRE_CFG_RC_BAD_PARAM;
+
+ sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sockfd < 0)
+ return LUSTRE_CFG_RC_BAD_PARAM;
+
+ strcpy(ifr->ifr_name, intf);
+ rc = ioctl(sockfd, request, ifr);
+ if (rc != 0)
+ return LUSTRE_CFG_RC_BAD_PARAM;
+
+ return 0;
+}
+
+/*
+ * for each interface in the array of interfaces find the IP address of
+ * that interface, create its nid and add it to an array of NIDs.
+ * Stop if any of the interfaces is down
+ */
+static int lustre_lnet_intf2nids(struct lnet_dlc_network_descr *nw,
+ lnet_nid_t **nids, __u32 *nnids)
+{
+ int i = 0, count = 0, rc;
+ struct ifreq ifr;
+ __u32 ip;
+ struct lnet_dlc_intf_descr *intf;
+
+ if (nw == NULL || nids == NULL)
+ return LUSTRE_CFG_RC_BAD_PARAM;
+
+ list_for_each_entry(intf, &nw->nw_intflist, intf_on_network)
+ count++;
+
+ *nids = calloc(count, sizeof(lnet_nid_t));
+ if (*nids == NULL)
+ return LUSTRE_CFG_RC_OUT_OF_MEM;
+
+ list_for_each_entry(intf, &nw->nw_intflist, intf_on_network) {
+ memset(&ifr, 0, sizeof(ifr));
+ rc = socket_intf_query(SIOCGIFFLAGS, intf->intf_name, &ifr);
+ if (rc != 0)
+ goto failed;
+
+ if ((ifr.ifr_flags & IFF_UP) == 0) {
+ rc = LUSTRE_CFG_RC_BAD_PARAM;
+ goto failed;
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+ rc = socket_intf_query(SIOCGIFADDR, intf->intf_name, &ifr);
+ if (rc != 0)
+ goto failed;
+
+ ip = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
+ ip = bswap_32(ip);
+ (*nids)[i] = LNET_MKNID(nw->nw_id, ip);
+ i++;
+ }
+
+ *nnids = count;
+
+ return 0;
+
+failed:
+ free(*nids);
+ *nids = NULL;
+ return rc;
+}
+
+/*
+ * called repeatedly until a match or no more ip range
+ * What do you have?
+ * ip_range expression
+ * interface list with all the interface names.
+ * all the interfaces in the system.
+ *
+ * try to match the ip_range expr to one of the interfaces' IPs in
+ * the system. If we hit a patch for an interface. Check if that
+ * interface name is in the list.
+ *
+ * If there are more than one interface in the list, then make sure
+ * that the IPs for all of these interfaces match the ip ranges
+ * given.
+ *
+ * for each interface in intf_list
+ * look up the intf name in ifa
+ * if not there then no match
+ * check ip obtained from ifa against a match to any of the
+ * ip_ranges given.
+ * If no match, then fail
+ *
+ * The result is that all the interfaces have to match.
+ */
+int lustre_lnet_match_ip_to_intf(struct ifaddrs *ifa,
+ struct list_head *intf_list,
+ struct list_head *ip_ranges)
+{
+ int rc;
+ __u32 ip;
+ struct lnet_dlc_intf_descr *intf_descr;
+ struct ifaddrs *ifaddr = ifa;
+ struct lustre_lnet_ip_range_descr *ip_range;
+ int family;
+
+ /*
+ * if there are no explicit interfaces, and no ip ranges, then
+ * configure the first tcp interface we encounter.
+ */
+ if (list_empty(intf_list) && list_empty(ip_ranges)) {
+ for (ifaddr = ifa; ifaddr != NULL; ifaddr = ifaddr->ifa_next) {
+ if (ifaddr->ifa_addr == NULL)
+ continue;
+
+ if ((ifaddr->ifa_flags & IFF_UP) == 0)
+ continue;
+
+ family = ifaddr->ifa_addr->sa_family;
+ if (family == AF_INET) {
+ rc = lustre_lnet_add_intf_descr
+ (intf_list, ifaddr->ifa_name,
+ strlen(ifaddr->ifa_name));
+
+ if (rc != LUSTRE_CFG_RC_NO_ERR)
+ return rc;
+
+ return LUSTRE_CFG_RC_MATCH;
+ }
+ }
+ return LUSTRE_CFG_RC_NO_MATCH;
+ }
+
+ /*
+ * First interface which matches an IP pattern will be used
+ */
+ if (list_empty(intf_list)) {
+ /*
+ * no interfaces provided in the rule, but an ip range is
+ * provided, so try and match an interface to the ip
+ * range.
+ */
+ for (ifaddr = ifa; ifaddr != NULL; ifaddr = ifaddr->ifa_next) {
+ if (ifaddr->ifa_addr == NULL)
+ continue;
+
+ if ((ifaddr->ifa_flags & IFF_UP) == 0)
+ continue;
+
+ family = ifaddr->ifa_addr->sa_family;
+ if (family == AF_INET) {
+ ip = ((struct sockaddr_in *)ifaddr->ifa_addr)->
+ sin_addr.s_addr;
+
+ list_for_each_entry(ip_range, ip_ranges,
+ ipr_entry) {
+ rc = cfs_ip_addr_match(bswap_32(ip),
+ &ip_range->ipr_expr);
+ if (!rc)
+ continue;
+
+ rc = lustre_lnet_add_intf_descr
+ (intf_list, ifaddr->ifa_name,
+ strlen(ifaddr->ifa_name));
+
+ if (rc != LUSTRE_CFG_RC_NO_ERR)
+ return rc;
+
+ return LUSTRE_CFG_RC_MATCH;
+ }
+ }
+ }
+ }
+
+ /*
+ * If an interface is explicitly specified the ip-range might or
+ * might not be specified. if specified the interface needs to match the
+ * ip-range. If no ip-range then the interfaces are
+ * automatically matched if they are all up.
+ * If > 1 interfaces all the interfaces must match for the NI to
+ * be configured.
+ */
+ list_for_each_entry(intf_descr, intf_list, intf_on_network) {
+ for (ifaddr = ifa; ifaddr != NULL; ifaddr = ifaddr->ifa_next) {
+ if (ifaddr->ifa_addr == NULL)
+ continue;
+
+ family = ifaddr->ifa_addr->sa_family;
+ if (family == AF_INET &&
+ strcmp(intf_descr->intf_name,
+ ifaddr->ifa_name) == 0)
+ break;
+ }
+
+ if (ifaddr == NULL)
+ return LUSTRE_CFG_RC_NO_MATCH;
+
+ if ((ifaddr->ifa_flags & IFF_UP) == 0)
+ return LUSTRE_CFG_RC_NO_MATCH;
+
+ ip = ((struct sockaddr_in *)ifaddr->ifa_addr)->sin_addr.s_addr;
+
+ list_for_each_entry(ip_range, ip_ranges, ipr_entry) {
+ rc = cfs_ip_addr_match(bswap_32(ip), &ip_range->ipr_expr);
+ if (rc)
+ break;
+ else
+ return LUSTRE_CFG_RC_NO_MATCH;
+ }
+ }
+
+ return LUSTRE_CFG_RC_MATCH;
+}
+
+int lustre_lnet_resolve_ip2nets_rule(struct lustre_lnet_ip2nets *ip2nets,
+ lnet_nid_t **nids, __u32 *nnids)
+{
+ struct ifaddrs *ifa;
int rc = LUSTRE_CFG_RC_NO_ERR;
+
+ rc = getifaddrs(&ifa);
+ if (rc < 0)
+ return -errno;
+
+ rc = lustre_lnet_match_ip_to_intf(ifa,
+ &ip2nets->ip2nets_net.nw_intflist,
+ &ip2nets->ip2nets_ip_ranges);
+ if (rc != LUSTRE_CFG_RC_MATCH) {
+ freeifaddrs(ifa);
+ return rc;
+ }
+
+ rc = lustre_lnet_intf2nids(&ip2nets->ip2nets_net, nids, nnids);
+ if (rc != LUSTRE_CFG_RC_NO_ERR) {
+ *nids = NULL;
+ *nnids = 0;
+ }
+
+ freeifaddrs(ifa);
+
+ return rc;
+}
+
+static int
+lustre_lnet_ioctl_config_ni(struct list_head *intf_list,
+ struct lnet_ioctl_config_lnd_tunables *tunables,
+ struct cfs_expr_list *global_cpts,
+ lnet_nid_t *nids, char *err_str)
+{
+ char *data;
+ struct lnet_ioctl_config_ni *conf;
+ struct lnet_ioctl_config_lnd_tunables *tun = NULL;
+ int rc = LUSTRE_CFG_RC_NO_ERR, i = 0;
+ size_t len;
+ int count;
+ struct lnet_dlc_intf_descr *intf_descr;
+ __u32 *cpt_array;
+ struct cfs_expr_list *cpt_expr;
+
+ list_for_each_entry(intf_descr, intf_list,
+ intf_on_network) {
+ if (i == 0 && tunables != NULL)
+ len = sizeof(struct lnet_ioctl_config_ni) +
+ sizeof(struct lnet_ioctl_config_lnd_tunables);
+ else
+ len = sizeof(struct lnet_ioctl_config_ni);
+
+ data = calloc(1, len);
+ conf = (struct lnet_ioctl_config_ni*) data;
+ if (i == 0 && tunables != NULL)
+ tun = (struct lnet_ioctl_config_lnd_tunables*)
+ (data + sizeof(*conf));
+
+ LIBCFS_IOC_INIT_V2(*conf, lic_cfg_hdr);
+ conf->lic_cfg_hdr.ioc_len = len;
+ conf->lic_nid = nids[i];
+ strncpy(conf->lic_ni_intf[0], intf_descr->intf_name,
+ LNET_MAX_STR_LEN);
+
+ if (intf_descr->cpt_expr != NULL)
+ cpt_expr = intf_descr->cpt_expr;
+ else if (global_cpts != NULL)
+ cpt_expr = global_cpts;
+ else
+ cpt_expr = NULL;
+
+ if (cpt_expr != NULL) {
+ count = cfs_expr_list_values(cpt_expr,
+ LNET_MAX_SHOW_NUM_CPT,
+ &cpt_array);
+ if (count > 0) {
+ memcpy(conf->lic_cpts, cpt_array,
+ sizeof(cpt_array[0]) * LNET_MAX_STR_LEN);
+ free(cpt_array);
+ } else {
+ count = 0;
+ }
+ } else {
+ count = 0;
+ }
+
+ conf->lic_ncpts = count;
+
+ if (i == 0 && tunables != NULL)
+ /* TODO put in the LND tunables */
+ memcpy(tun, tunables, sizeof(*tunables));
+
+ rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_ADD_LOCAL_NI, data);
+ if (rc < 0) {
+ rc = -errno;
+ snprintf(err_str,
+ LNET_MAX_STR_LEN,
+ "\"cannot add network: %s\"", strerror(errno));
+ return rc;
+ }
+ i++;
+ }
+
+ return LUSTRE_CFG_RC_NO_ERR;
+}
+
+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)
+{
+ lnet_nid_t *nids = NULL;
+ __u32 nnids = 0;
+ int rc;
char err_str[LNET_MAX_STR_LEN];
snprintf(err_str, sizeof(err_str), "\"success\"");
- /* No need to register lo */
- if (net != NULL && !strcmp(net, "lo"))
- return 0;
+ if (ip2nets == NULL ||
+ list_empty(&ip2nets->ip2nets_net.nw_intflist)) {
+ snprintf(err_str,
+ sizeof(err_str),
+ "\"incomplete ip2nets information\"");
+ rc = LUSTRE_CFG_RC_BAD_PARAM;
+ goto out;
+ }
- if (ip2net == NULL && (intf == NULL || net == NULL)) {
+ rc = lustre_lnet_resolve_ip2nets_rule(ip2nets, &nids, &nnids);
+ if (rc != LUSTRE_CFG_RC_NO_ERR && rc != LUSTRE_CFG_RC_MATCH) {
snprintf(err_str,
sizeof(err_str),
- "\"mandatory parameter '%s' not specified."
- " Optionally specify ip2net parameter\"",
- (intf == NULL && net == NULL) ? "net, if" :
- (intf == NULL) ? "if" : "net");
- rc = LUSTRE_CFG_RC_MISSING_PARAM;
+ "\"cannot resolve ip2nets rule\"");
goto out;
}
- if (peer_to != -1 && peer_to <= 0) {
+ rc = lustre_lnet_ioctl_config_ni(&ip2nets->ip2nets_net.nw_intflist,
+ tunables, global_cpts, nids,
+ err_str);
+ if (rc != LUSTRE_CFG_RC_NO_ERR)
+ free(nids);
+
+out:
+ cYAML_build_error(rc, seq_no, ADD_CMD, "ip2nets", err_str, err_rc);
+ return rc;
+}
+
+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)
+{
+ char *data = NULL;
+ struct lnet_ioctl_config_ni *conf;
+ struct lnet_ioctl_config_lnd_tunables *tun = NULL;
+ char buf[LNET_MAX_STR_LEN];
+ int rc = LUSTRE_CFG_RC_NO_ERR;
+ char err_str[LNET_MAX_STR_LEN];
+ lnet_nid_t *nids = NULL;
+ __u32 nnids = 0;
+ size_t len;
+ int count;
+ struct lnet_dlc_intf_descr *intf_descr, *tmp;
+ __u32 *cpt_array;
+
+ snprintf(err_str, sizeof(err_str), "\"success\"");
+
+ if (ip2net == NULL && nw_descr == NULL) {
snprintf(err_str,
sizeof(err_str),
- "\"peer timeout %d, must be greater than 0\"",
- peer_to);
- rc = LUSTRE_CFG_RC_OUT_OF_RANGE_PARAM;
+ "\"mandatory parameters not specified.\"");
+ rc = LUSTRE_CFG_RC_MISSING_PARAM;
goto out;
}
goto out;
}
- if (lnd_tunables != NULL)
- ioctl_size += sizeof(*lnd_tunables);
+ if (ip2net != NULL) {
+ if (tunables != NULL)
+ len = sizeof(struct lnet_ioctl_config_ni) +
+ sizeof(struct lnet_ioctl_config_lnd_tunables);
+ else
+ len = sizeof(struct lnet_ioctl_config_ni);
+ data = calloc(1, len);
+ conf = (struct lnet_ioctl_config_ni*) data;
+ if (tunables != NULL)
+ tun = (struct lnet_ioctl_config_lnd_tunables*)
+ (data + sizeof(*conf));
+
+ LIBCFS_IOC_INIT_V2(*conf, lic_cfg_hdr);
+ conf->lic_cfg_hdr.ioc_len = len;
+ strncpy(conf->lic_legacy_ip2nets, ip2net,
+ LNET_MAX_STR_LEN);
+
+ if (global_cpts != NULL) {
+ count = cfs_expr_list_values(global_cpts,
+ LNET_MAX_SHOW_NUM_CPT,
+ &cpt_array);
+ if (count > 0) {
+ memcpy(conf->lic_cpts, cpt_array,
+ sizeof(cpt_array[0]) * LNET_MAX_STR_LEN);
+ free(cpt_array);
+ } else {
+ count = 0;
+ }
+ } else {
+ count = 0;
+ }
- data = calloc(1, ioctl_size);
- if (data == NULL)
- goto out;
+ conf->lic_ncpts = count;
- if (ip2net == NULL)
- snprintf(buf, sizeof(buf) - 1, "%s(%s)%s",
- net, intf,
- (smp) ? smp : "");
+ if (tunables != NULL)
+ memcpy(tun, tunables, sizeof(*tunables));
- LIBCFS_IOC_INIT_V2(*data, cfg_hdr);
- strncpy(data->cfg_config_u.cfg_net.net_intf,
- (ip2net != NULL) ? ip2net : buf, sizeof(buf));
- data->cfg_config_u.cfg_net.net_peer_timeout = peer_to;
- data->cfg_config_u.cfg_net.net_peer_tx_credits = peer_cr;
- data->cfg_config_u.cfg_net.net_peer_rtr_credits = peer_buf_cr;
- data->cfg_config_u.cfg_net.net_max_tx_credits = credits;
- /* Add in tunable settings if available */
- if (lnd_tunables != NULL) {
- lnd = (struct lnet_ioctl_config_lnd_tunables *)data->cfg_bulk;
+ rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_ADD_LOCAL_NI, data);
+ if (rc < 0) {
+ rc = -errno;
+ snprintf(err_str,
+ sizeof(err_str),
+ "\"cannot add network: %s\"", strerror(errno));
+ goto out;
+ }
- data->cfg_hdr.ioc_len = ioctl_size;
- memcpy(lnd, lnd_tunables, sizeof(*lnd_tunables));
+ goto out;
}
- rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_ADD_NET, data);
- if (rc < 0) {
- rc = -errno;
+ if (LNET_NETTYP(nw_descr->nw_id) == LOLND)
+ return LUSTRE_CFG_RC_NO_ERR;
+
+ if (nw_descr->nw_id == LNET_NIDNET(LNET_NID_ANY)) {
snprintf(err_str,
- sizeof(err_str),
- "\"cannot add network: %s\"", strerror(errno));
+ sizeof(err_str),
+ "\"cannot parse net '%s'\"",
+ libcfs_net2str(nw_descr->nw_id));
+ rc = LUSTRE_CFG_RC_BAD_PARAM;
+ goto out;
}
- free(data);
+
+ if (list_empty(&nw_descr->nw_intflist)) {
+ snprintf(err_str,
+ sizeof(err_str),
+ "\"no interface name provided\"");
+ rc = LUSTRE_CFG_RC_BAD_PARAM;
+ goto out;
+ }
+
+ rc = lustre_lnet_intf2nids(nw_descr, &nids, &nnids);
+ if (rc != 0) {
+ snprintf(err_str, sizeof(err_str),
+ "\"bad parameter\"");
+ rc = LUSTRE_CFG_RC_BAD_PARAM;
+ goto out;
+ }
+
+ rc = lustre_lnet_ioctl_config_ni(&nw_descr->nw_intflist,
+ tunables, global_cpts, nids,
+ err_str);
out:
+ if (nw_descr != NULL) {
+ list_for_each_entry_safe(intf_descr, tmp,
+ &nw_descr->nw_intflist,
+ intf_on_network) {
+ if (intf_descr->cpt_expr != NULL)
+ cfs_expr_list_free(intf_descr->cpt_expr);
+ free(intf_descr);
+ }
+ }
+
cYAML_build_error(rc, seq_no, ADD_CMD, "net", err_str, err_rc);
+ if (nids)
+ free(nids);
+
+ if (data)
+ free(data);
+
return rc;
}
-int lustre_lnet_del_net(char *nw, int seq_no, struct cYAML **err_rc)
+int lustre_lnet_del_ni(struct lnet_dlc_network_descr *nw_descr,
+ int seq_no, struct cYAML **err_rc)
{
- struct lnet_ioctl_config_data data;
- __u32 net = LNET_NIDNET(LNET_NID_ANY);
- int rc = LUSTRE_CFG_RC_NO_ERR;
+ struct lnet_ioctl_config_ni data;
+ int rc = LUSTRE_CFG_RC_NO_ERR, i;
char err_str[LNET_MAX_STR_LEN];
+ lnet_nid_t *nids = NULL;
+ __u32 nnids = 0;
+ struct lnet_dlc_intf_descr *intf_descr, *tmp;
+
+ if (LNET_NETTYP(nw_descr->nw_id) == LOLND)
+ return LUSTRE_CFG_RC_NO_ERR;
snprintf(err_str, sizeof(err_str), "\"success\"");
- if (nw == NULL) {
+ if (nw_descr == NULL) {
snprintf(err_str,
sizeof(err_str),
"\"missing mandatory parameter\"");
goto out;
}
- net = libcfs_str2net(nw);
- if (net == LNET_NIDNET(LNET_NID_ANY)) {
+ if (nw_descr->nw_id == LNET_NIDNET(LNET_NID_ANY)) {
snprintf(err_str,
sizeof(err_str),
- "\"cannot parse net '%s'\"", nw);
+ "\"cannot parse net '%s'\"",
+ libcfs_net2str(nw_descr->nw_id));
rc = LUSTRE_CFG_RC_BAD_PARAM;
goto out;
}
- LIBCFS_IOC_INIT_V2(data, cfg_hdr);
- data.cfg_net = net;
-
- rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_DEL_NET, &data);
+ rc = lustre_lnet_intf2nids(nw_descr, &nids, &nnids);
if (rc != 0) {
- rc = -errno;
- snprintf(err_str,
- sizeof(err_str),
- "\"cannot delete network: %s\"", strerror(errno));
+ snprintf(err_str, sizeof(err_str),
+ "\"bad parameter\"");
+ rc = LUSTRE_CFG_RC_BAD_PARAM;
goto out;
}
+ /*
+ * no interfaces just the nw_id is specified
+ */
+ if (nnids == 0) {
+ nids = calloc(1, sizeof(*nids));
+ if (nids == NULL) {
+ snprintf(err_str, sizeof(err_str),
+ "\"out of memory\"");
+ rc = LUSTRE_CFG_RC_OUT_OF_MEM;
+ goto out;
+ }
+ nids[0] = LNET_MKNID(nw_descr->nw_id, 0);
+ nnids = 1;
+ }
+
+ for (i = 0; i < nnids; i++) {
+ LIBCFS_IOC_INIT_V2(data, lic_cfg_hdr);
+ data.lic_nid = nids[i];
+
+ rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_DEL_LOCAL_NI, &data);
+ if (rc < 0) {
+ rc = -errno;
+ snprintf(err_str,
+ sizeof(err_str),
+ "\"cannot del network: %s\"", strerror(errno));
+ }
+ }
+
+ list_for_each_entry_safe(intf_descr, tmp, &nw_descr->nw_intflist,
+ intf_on_network) {
+ if (intf_descr->cpt_expr != NULL)
+ cfs_expr_list_free(intf_descr->cpt_expr);
+ free(intf_descr);
+ }
+
out:
cYAML_build_error(rc, seq_no, DEL_CMD, "net", err_str, err_rc);
+ if (nids != NULL)
+ free(nids);
+
return rc;
}
struct cYAML **show_rc, struct cYAML **err_rc)
{
char *buf;
- struct lnet_ioctl_config_lnd_tunables *lnd_cfg;
- struct lnet_ioctl_config_data *data;
- struct lnet_ioctl_net_config *net_config;
+ struct lnet_ioctl_config_ni *ni_data;
+ struct lnet_ioctl_config_lnd_tunables *lnd;
__u32 net = LNET_NIDNET(LNET_NID_ANY);
+ __u32 prev_net = LNET_NIDNET(LNET_NID_ANY);
int rc = LUSTRE_CFG_RC_OUT_OF_MEM, i, j;
int l_errno = 0;
- struct cYAML *root = NULL, *tunables = NULL, *net_node = NULL,
- *interfaces = NULL, *item = NULL, *first_seq = NULL;
+ struct cYAML *root = NULL, *tunables = NULL,
+ *net_node = NULL, *interfaces = NULL,
+ *item = NULL, *first_seq = NULL,
+ *tmp = NULL;
int str_buf_len = LNET_MAX_SHOW_NUM_CPT * 2;
char str_buf[str_buf_len];
char *pos;
char err_str[LNET_MAX_STR_LEN];
- bool exist = false;
- size_t buf_len;
+ bool exist = false, new_net = true;
+ int net_num = 0;
+ size_t buf_size = sizeof(*ni_data) + sizeof(*lnd);
snprintf(err_str, sizeof(err_str), "\"out of memory\"");
- buf_len = sizeof(*data) + sizeof(*net_config) + sizeof(*lnd_cfg);
- buf = calloc(1, buf_len);
+ buf = calloc(1, buf_size);
if (buf == NULL)
goto out;
- data = (struct lnet_ioctl_config_data *)buf;
+ ni_data = (struct lnet_ioctl_config_ni *)buf;
if (nw != NULL) {
net = libcfs_str2net(nw);
for (i = 0;; i++) {
pos = str_buf;
+ __u32 rc_net;
- memset(buf, 0, buf_len);
+ memset(buf, 0, buf_size);
- LIBCFS_IOC_INIT_V2(*data, cfg_hdr);
+ LIBCFS_IOC_INIT_V2(*ni_data, lic_cfg_hdr);
/*
* set the ioc_len to the proper value since INIT assumes
* size of data
*/
- data->cfg_hdr.ioc_len = buf_len;
- data->cfg_count = i;
+ ni_data->lic_cfg_hdr.ioc_len = buf_size;
+ ni_data->lic_idx = i;
- rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_NET, data);
+ rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_GET_LOCAL_NI, ni_data);
if (rc != 0) {
l_errno = errno;
break;
}
+ rc_net = LNET_NIDNET(ni_data->lic_nid);
+
/* filter on provided data */
if (net != LNET_NIDNET(LNET_NID_ANY) &&
- net != LNET_NIDNET(data->cfg_nid))
+ net != rc_net)
continue;
/* default rc to -1 in case we hit the goto */
rc = -1;
exist = true;
- net_config = (struct lnet_ioctl_net_config *)data->cfg_bulk;
+ lnd = (struct lnet_ioctl_config_lnd_tunables *)ni_data->lic_bulk;
+
+ if (rc_net != prev_net) {
+ prev_net = rc_net;
+ new_net = true;
+ net_num++;
+ }
+
+ if (new_net) {
+ if (!cYAML_create_string(net_node, "net type",
+ libcfs_net2str(rc_net)))
+ goto out;
+
+ tmp = cYAML_create_seq(net_node, "local NI(s)");
+ if (tmp == NULL)
+ goto out;
+ new_net = false;
+ }
/* create the tree to be printed. */
- item = cYAML_create_seq_item(net_node);
+ item = cYAML_create_seq_item(tmp);
if (item == NULL)
goto out;
if (first_seq == NULL)
first_seq = item;
- if (cYAML_create_string(item, "net",
- libcfs_net2str(
- LNET_NIDNET(data->cfg_nid)))
- == NULL)
- goto out;
-
if (cYAML_create_string(item, "nid",
- libcfs_nid2str(data->cfg_nid)) == NULL)
+ libcfs_nid2str(ni_data->lic_nid)) == NULL)
goto out;
- if (cYAML_create_string(item, "status",
- (net_config->ni_status ==
+ if (cYAML_create_string(item,
+ "status",
+ (ni_data->lic_status ==
LNET_NI_STATUS_UP) ?
"up" : "down") == NULL)
goto out;
/* don't add interfaces unless there is at least one
* interface */
- if (strlen(net_config->ni_interfaces[0]) > 0) {
+ if (strlen(ni_data->lic_ni_intf[0]) > 0) {
interfaces = cYAML_create_object(item, "interfaces");
if (interfaces == NULL)
goto out;
for (j = 0; j < LNET_MAX_INTERFACES; j++) {
- if (lustre_interface_show_net(interfaces, j,
- detail, data,
- net_config) < 0)
- goto out;
+ if (strlen(ni_data->lic_ni_intf[j]) > 0) {
+ snprintf(str_buf,
+ sizeof(str_buf), "%d", j);
+ if (cYAML_create_string(interfaces,
+ str_buf,
+ ni_data->lic_ni_intf[j]) ==
+ NULL)
+ goto out;
+ }
}
}
char *limit;
tunables = cYAML_create_object(item, "tunables");
- if (tunables == NULL)
+ if (!tunables)
goto out;
- if (cYAML_create_number(tunables, "peer_timeout",
- data->cfg_config_u.cfg_net.
- net_peer_timeout) == NULL)
+ rc = lustre_net_show_tunables(tunables, &lnd->lt_cmn);
+ if (rc != LUSTRE_CFG_RC_NO_ERR)
goto out;
- if (cYAML_create_number(tunables, "peer_credits",
- data->cfg_config_u.cfg_net.
- net_peer_tx_credits) == NULL)
+ tunables = cYAML_create_object(item, "lnd tunables");
+ if (tunables == NULL)
goto out;
- if (cYAML_create_number(tunables,
- "peer_buffer_credits",
- data->cfg_config_u.cfg_net.
- net_peer_rtr_credits) == NULL)
+ rc = lustre_ni_show_tunables(tunables, LNET_NETTYP(rc_net),
+ &lnd->lt_tun);
+ if (rc != LUSTRE_CFG_RC_NO_ERR)
goto out;
- if (cYAML_create_number(tunables, "credits",
- data->cfg_config_u.cfg_net.
- net_max_tx_credits) == NULL)
+ if (cYAML_create_number(item, "tcp bonding",
+ ni_data->lic_tcp_bonding)
+ == NULL)
goto out;
/* out put the CPTs in the format: "[x,x,x,...]" */
limit = str_buf + str_buf_len - 3;
pos += snprintf(pos, limit - pos, "\"[");
- for (j = 0 ; data->cfg_ncpts > 1 &&
- j < data->cfg_ncpts &&
+ for (j = 0 ; ni_data->lic_ncpts >= 1 &&
+ j < ni_data->lic_ncpts &&
pos < limit; j++) {
pos += snprintf(pos, limit - pos,
- "%d", net_config->ni_cpts[j]);
- if ((j + 1) < data->cfg_ncpts)
+ "%d", ni_data->lic_cpts[j]);
+ if ((j + 1) < ni_data->lic_ncpts)
pos += snprintf(pos, limit - pos, ",");
}
pos += snprintf(pos, 3, "]\"");
- if (data->cfg_ncpts > 1 &&
- cYAML_create_string(tunables, "CPT",
+ if (ni_data->lic_ncpts >= 1 &&
+ cYAML_create_string(item, "CPT",
str_buf) == NULL)
goto out;
}
err_rc);
}
-static int handle_yaml_config_net(struct cYAML *tree, struct cYAML **show_rc,
- struct cYAML **err_rc)
+static void yaml_free_string_array(char **array, int num)
+{
+ int i;
+ char **sub_array = array;
+
+ for (i = 0; i < num; i++) {
+ if (*sub_array != NULL)
+ free(sub_array);
+ sub_array++;
+ }
+ free(array);
+}
+
+/*
+ * interfaces:
+ * 0: <intf_name>['['<expr>']']
+ * 1: <intf_name>['['<expr>']']
+ */
+static int yaml_copy_intf_info(struct cYAML *intf_tree,
+ struct lnet_dlc_network_descr *nw_descr)
+{
+ struct cYAML *child = NULL;
+ int intf_num = 0, rc = LUSTRE_CFG_RC_NO_ERR;
+ struct lnet_dlc_intf_descr *intf_descr, *tmp;
+
+ if (intf_tree == NULL || nw_descr == NULL)
+ return LUSTRE_CFG_RC_BAD_PARAM;
+
+ /* now grab all the interfaces and their cpts */
+ child = intf_tree->cy_child;
+ while (child != NULL) {
+ if (child->cy_valuestring == NULL) {
+ child = child->cy_next;
+ continue;
+ }
+
+ if (strlen(child->cy_valuestring) >= LNET_MAX_STR_LEN)
+ goto failed;
+
+ rc = lustre_lnet_add_intf_descr(&nw_descr->nw_intflist,
+ child->cy_valuestring,
+ strlen(child->cy_valuestring));
+ if (rc != LUSTRE_CFG_RC_NO_ERR)
+ goto failed;
+
+ intf_num++;
+ child = child->cy_next;
+ }
+
+ if (intf_num == 0)
+ return LUSTRE_CFG_RC_MISSING_PARAM;
+
+ return intf_num;
+
+failed:
+ list_for_each_entry_safe(intf_descr, tmp, &nw_descr->nw_intflist,
+ intf_on_network) {
+ if (intf_descr->cpt_expr != NULL)
+ cfs_expr_list_free(intf_descr->cpt_expr);
+ free(intf_descr);
+ }
+
+ return rc;
+}
+
+static bool
+yaml_extract_cmn_tunables(struct cYAML *tree,
+ struct lnet_ioctl_config_lnd_cmn_tunables *tunables,
+ int *num_global_cpts,
+ struct cfs_expr_list **global_cpts)
+{
+ struct cYAML *tun, *item, *smp;
+
+ tun = cYAML_get_object_item(tree, "tunables");
+ if (tun != NULL) {
+ item = cYAML_get_object_item(tun, "peer_timeout");
+ if (item != NULL)
+ tunables->lct_peer_timeout = item->cy_valueint;
+ item = cYAML_get_object_item(tun, "peer_credits");
+ if (item != NULL)
+ tunables->lct_peer_tx_credits = item->cy_valueint;
+ item = cYAML_get_object_item(tun, "peer_buffer_credits");
+ if (item != NULL)
+ tunables->lct_peer_rtr_credits = item->cy_valueint;
+ item = cYAML_get_object_item(tun, "credits");
+ if (item != NULL)
+ tunables->lct_max_tx_credits = item->cy_valueint;
+ smp = cYAML_get_object_item(tun, "CPT");
+ if (smp != NULL) {
+ *num_global_cpts =
+ cfs_expr_list_parse(smp->cy_valuestring,
+ strlen(smp->cy_valuestring),
+ 0, UINT_MAX, global_cpts);
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+static bool
+yaml_extract_tunables(struct cYAML *tree,
+ struct lnet_ioctl_config_lnd_tunables *tunables,
+ int *num_global_cpts,
+ struct cfs_expr_list **global_cpts,
+ __u32 net_type)
+{
+ bool rc;
+
+ rc = yaml_extract_cmn_tunables(tree, &tunables->lt_cmn,
+ num_global_cpts, global_cpts);
+
+ if (!rc)
+ return rc;
+
+ lustre_yaml_extract_lnd_tunables(tree, net_type,
+ &tunables->lt_tun);
+
+ return rc;
+}
+
+/*
+ * net:
+ * - net type: <net>[<NUM>]
+ * local NI(s):
+ * - nid: <ip>@<net>[<NUM>]
+ * status: up
+ * interfaces:
+ * 0: <intf_name>['['<expr>']']
+ * 1: <intf_name>['['<expr>']']
+ * tunables:
+ * peer_timeout: <NUM>
+ * peer_credits: <NUM>
+ * peer_buffer_credits: <NUM>
+ * credits: <NUM>
+* lnd tunables:
+ * peercredits_hiw: <NUM>
+ * map_on_demand: <NUM>
+ * concurrent_sends: <NUM>
+ * fmr_pool_size: <NUM>
+ * fmr_flush_trigger: <NUM>
+ * fmr_cache: <NUM>
+ *
+ * At least one interface is required. If no interfaces are provided the
+ * network interface can not be configured.
+ */
+static int handle_yaml_config_ni(struct cYAML *tree, struct cYAML **show_rc,
+ struct cYAML **err_rc)
{
- struct cYAML *net, *intf, *tunables, *seq_no,
- *peer_to = NULL, *peer_buf_cr = NULL, *peer_cr = NULL,
- *credits = NULL, *ip2net = NULL, *smp = NULL, *child;
- struct lnet_ioctl_config_lnd_tunables *lnd_tunables_p = NULL;
- struct lnet_ioctl_config_lnd_tunables lnd_tunables;
- char devs[LNET_MAX_STR_LEN];
- char *loc = devs;
- int size = LNET_MAX_STR_LEN;
- int num;
- bool intf_found = false;
+ struct cYAML *net, *intf, *seq_no, *ip2net = NULL, *local_nis = NULL,
+ *item = NULL;
+ int num_entries = 0, num_global_cpts = 0, rc;
+ struct lnet_dlc_network_descr nw_descr;
+ struct cfs_expr_list *global_cpts = NULL;
+ struct lnet_ioctl_config_lnd_tunables tunables;
+ bool found = false;
+
+ memset(&tunables, 0, sizeof(tunables));
+
+ INIT_LIST_HEAD(&nw_descr.network_on_rule);
+ INIT_LIST_HEAD(&nw_descr.nw_intflist);
ip2net = cYAML_get_object_item(tree, "ip2net");
- net = cYAML_get_object_item(tree, "net");
+ net = cYAML_get_object_item(tree, "net type");
+ if (net)
+ nw_descr.nw_id = libcfs_str2net(net->cy_valuestring);
+
+ /*
+ * if neither net nor ip2nets are present, then we can not
+ * configure the network.
+ */
+ if (!net && !ip2net)
+ return LUSTRE_CFG_RC_MISSING_PARAM;
+
+ local_nis = cYAML_get_object_item(tree, "local NI(s)");
+ if (local_nis == NULL)
+ return LUSTRE_CFG_RC_MISSING_PARAM;
+
+ if (!cYAML_is_sequence(local_nis))
+ return LUSTRE_CFG_RC_BAD_PARAM;
+
+ while (cYAML_get_next_seq_item(local_nis, &item) != NULL) {
+ intf = cYAML_get_object_item(item, "interfaces");
+ if (intf == NULL)
+ continue;
+ num_entries = yaml_copy_intf_info(intf, &nw_descr);
+ if (num_entries <= 0) {
+ cYAML_build_error(num_entries, -1, "ni", "add",
+ "bad interface list",
+ err_rc);
+ return LUSTRE_CFG_RC_BAD_PARAM;
+ }
+ }
+
+ found = yaml_extract_tunables(tree, &tunables, &num_global_cpts,
+ &global_cpts,
+ LNET_NETTYP(nw_descr.nw_id));
+ seq_no = cYAML_get_object_item(tree, "seq_no");
+
+ rc = lustre_lnet_config_ni(&nw_descr,
+ (num_global_cpts > 0) ? global_cpts: NULL,
+ (ip2net) ? ip2net->cy_valuestring : NULL,
+ (found) ? &tunables: NULL,
+ (seq_no) ? seq_no->cy_valueint : -1,
+ err_rc);
+
+ if (global_cpts != NULL)
+ cfs_expr_list_free(global_cpts);
+
+ return rc;
+}
+
+/*
+ * ip2nets:
+ * - net-spec: <tcp|o2ib|gni>[NUM]
+ * interfaces:
+ * 0: <intf name>['['<expr>']']
+ * 1: <intf name>['['<expr>']']
+ * ip-range:
+ * 0: <expr.expr.expr.expr>
+ * 1: <expr.expr.expr.expr>
+ */
+static int handle_yaml_config_ip2nets(struct cYAML *tree,
+ struct cYAML **show_rc,
+ struct cYAML **err_rc)
+{
+ struct cYAML *net, *ip_range, *item = NULL, *intf = NULL,
+ *seq_no = NULL;
+ struct lustre_lnet_ip2nets ip2nets;
+ struct lustre_lnet_ip_range_descr *ip_range_descr = NULL,
+ *tmp = NULL;
+ int rc = LUSTRE_CFG_RC_NO_ERR, num_global_cpts = 0;
+ struct cfs_expr_list *global_cpts = NULL;
+ struct cfs_expr_list *el, *el_tmp;
+ struct lnet_ioctl_config_lnd_tunables tunables;
+ struct lnet_dlc_intf_descr *intf_descr, *intf_tmp;
+ bool found = false;
+
+ memset(&tunables, 0, sizeof(tunables));
+
+ /* initialize all lists */
+ INIT_LIST_HEAD(&ip2nets.ip2nets_ip_ranges);
+ INIT_LIST_HEAD(&ip2nets.ip2nets_net.network_on_rule);
+ INIT_LIST_HEAD(&ip2nets.ip2nets_net.nw_intflist);
+
+ net = cYAML_get_object_item(tree, "net-spec");
+ if (net == NULL)
+ return LUSTRE_CFG_RC_BAD_PARAM;
+
+ if (net != NULL && net->cy_valuestring == NULL)
+ return LUSTRE_CFG_RC_BAD_PARAM;
+
+ /* assign the network id */
+ ip2nets.ip2nets_net.nw_id = libcfs_str2net(net->cy_valuestring);
+ if (ip2nets.ip2nets_net.nw_id == LNET_NID_ANY)
+ return LUSTRE_CFG_RC_BAD_PARAM;
+
+ seq_no = cYAML_get_object_item(tree, "seq_no");
+
intf = cYAML_get_object_item(tree, "interfaces");
if (intf != NULL) {
- /* grab all the interfaces */
- child = intf->cy_child;
- while (child != NULL && size > 0) {
- struct cYAML *lnd_params;
-
- if (child->cy_valuestring == NULL)
- goto ignore_child;
+ rc = yaml_copy_intf_info(intf, &ip2nets.ip2nets_net);
+ if (rc <= 0)
+ return LUSTRE_CFG_RC_BAD_PARAM;
+ }
- if (loc > devs)
- num = snprintf(loc, size, ",%s",
- child->cy_valuestring);
- else
- num = snprintf(loc, size, "%s",
- child->cy_valuestring);
- size -= num;
- loc += num;
- intf_found = true;
-
- lnd_params = cYAML_get_object_item(intf,
- "lnd tunables");
- if (lnd_params != NULL) {
- const char *dev_name = child->cy_valuestring;
- lnd_tunables_p = &lnd_tunables;
-
- lustre_interface_parse(lnd_params, dev_name,
- lnd_tunables_p);
+ ip_range = cYAML_get_object_item(tree, "ip-range");
+ if (ip_range != NULL) {
+ item = ip_range->cy_child;
+ while (item != NULL) {
+ if (item->cy_valuestring == NULL) {
+ item = item->cy_next;
+ continue;
}
-ignore_child:
- child = child->cy_next;
+
+ rc = lustre_lnet_add_ip_range(&ip2nets.ip2nets_ip_ranges,
+ item->cy_valuestring);
+
+ if (rc != LUSTRE_CFG_RC_NO_ERR)
+ goto out;
+
+ item = item->cy_next;
}
}
- tunables = cYAML_get_object_item(tree, "tunables");
- if (tunables != NULL) {
- peer_to = cYAML_get_object_item(tunables, "peer_timeout");
- peer_cr = cYAML_get_object_item(tunables, "peer_credits");
- peer_buf_cr = cYAML_get_object_item(tunables,
- "peer_buffer_credits");
- credits = cYAML_get_object_item(tunables, "credits");
- smp = cYAML_get_object_item(tunables, "CPT");
+ found = yaml_extract_tunables(tree, &tunables, &num_global_cpts,
+ &global_cpts,
+ LNET_NETTYP(ip2nets.ip2nets_net.nw_id));
+
+ rc = lustre_lnet_config_ip2nets(&ip2nets,
+ (found) ? &tunables : NULL,
+ (num_global_cpts > 0) ? global_cpts : NULL,
+ (seq_no) ? seq_no->cy_valueint : -1,
+ err_rc);
+
+ /*
+ * don't stop because there was no match. Continue processing the
+ * rest of the rules. If non-match then nothing is configured
+ */
+ if (rc == LUSTRE_CFG_RC_NO_MATCH)
+ rc = LUSTRE_CFG_RC_NO_ERR;
+out:
+ list_for_each_entry_safe(intf_descr, intf_tmp,
+ &ip2nets.ip2nets_net.nw_intflist,
+ intf_on_network) {
+ if (intf_descr->cpt_expr != NULL)
+ cfs_expr_list_free(intf_descr->cpt_expr);
+ free(intf_descr);
}
- seq_no = cYAML_get_object_item(tree, "seq_no");
- return lustre_lnet_config_net((net) ? net->cy_valuestring : NULL,
- (intf_found) ? devs : NULL,
- (ip2net) ? ip2net->cy_valuestring : NULL,
- (peer_to) ? peer_to->cy_valueint : -1,
- (peer_cr) ? peer_cr->cy_valueint : -1,
- (peer_buf_cr) ?
- peer_buf_cr->cy_valueint : -1,
- (credits) ? credits->cy_valueint : -1,
- (smp) ? smp->cy_valuestring : NULL,
- (seq_no) ? seq_no->cy_valueint : -1,
- lnd_tunables_p,
- err_rc);
+ list_for_each_entry_safe(ip_range_descr, tmp,
+ &ip2nets.ip2nets_ip_ranges,
+ ipr_entry) {
+ list_for_each_entry_safe(el, el_tmp, &ip_range_descr->ipr_expr,
+ el_link)
+ cfs_expr_list_free(el);
+ free(ip_range_descr);
+ }
+
+ return rc;
}
-static void yaml_free_string_array(char **str_array, int num)
+static int handle_yaml_del_ni(struct cYAML *tree, struct cYAML **show_rc,
+ struct cYAML **err_rc)
{
- int i;
+ struct cYAML *net = NULL, *intf = NULL, *seq_no = NULL, *item = NULL,
+ *local_nis = NULL;
+ int num_entries, rc;
+ struct lnet_dlc_network_descr nw_descr;
+
+ INIT_LIST_HEAD(&nw_descr.network_on_rule);
+ INIT_LIST_HEAD(&nw_descr.nw_intflist);
+
+ net = cYAML_get_object_item(tree, "net type");
+ if (net != NULL)
+ nw_descr.nw_id = libcfs_str2net(net->cy_valuestring);
+
+ local_nis = cYAML_get_object_item(tree, "local NI(s)");
+ if (local_nis == NULL)
+ return LUSTRE_CFG_RC_MISSING_PARAM;
+
+ if (!cYAML_is_sequence(local_nis))
+ return LUSTRE_CFG_RC_BAD_PARAM;
+
+ while (cYAML_get_next_seq_item(local_nis, &item) != NULL) {
+ intf = cYAML_get_object_item(item, "interfaces");
+ if (intf == NULL)
+ continue;
+ num_entries = yaml_copy_intf_info(intf, &nw_descr);
+ if (num_entries <= 0) {
+ cYAML_build_error(num_entries, -1, "ni", "add",
+ "bad interface list",
+ err_rc);
+ return LUSTRE_CFG_RC_BAD_PARAM;
+ }
+ }
- for (i = 0; i < num; i++)
- free(str_array[num]);
- free(str_array);
+ seq_no = cYAML_get_object_item(tree, "seq_no");
+
+ rc = lustre_lnet_del_ni((net) ? &nw_descr : NULL,
+ (seq_no) ? seq_no->cy_valueint : -1,
+ err_rc);
+
+ return rc;
}
static int yaml_copy_peer_nids(struct cYAML *tree, char ***nidsppp)
err_rc);
}
-static int handle_yaml_del_net(struct cYAML *tree, struct cYAML **show_rc,
- struct cYAML **err_rc)
-{
- struct cYAML *net, *seq_no;
-
- net = cYAML_get_object_item(tree, "net");
- seq_no = cYAML_get_object_item(tree, "seq_no");
-
- return lustre_lnet_del_net((net) ? net->cy_valuestring : NULL,
- (seq_no) ? seq_no->cy_valueint : -1,
- err_rc);
-}
-
static int handle_yaml_del_routing(struct cYAML *tree, struct cYAML **show_rc,
struct cYAML **err_rc)
{
static struct lookup_cmd_hdlr_tbl lookup_config_tbl[] = {
{"route", handle_yaml_config_route},
- {"net", handle_yaml_config_net},
+ {"net", handle_yaml_config_ni},
+ {"ip2nets", handle_yaml_config_ip2nets},
{"peer", handle_yaml_config_peer},
{"routing", handle_yaml_config_routing},
{"buffers", handle_yaml_config_buffers},
static struct lookup_cmd_hdlr_tbl lookup_del_tbl[] = {
{"route", handle_yaml_del_route},
- {"net", handle_yaml_del_net},
+ {"net", handle_yaml_del_ni},
{"peer", handle_yaml_del_peer},
{"routing", handle_yaml_del_routing},
{NULL, NULL}
char err_str[LNET_MAX_STR_LEN];
int rc = LUSTRE_CFG_RC_NO_ERR, return_rc = LUSTRE_CFG_RC_NO_ERR;
- tree = cYAML_build_tree(f, NULL, 0, err_rc);
+ tree = cYAML_build_tree(f, NULL, 0, err_rc, false);
if (tree == NULL)
return LUSTRE_CFG_RC_BAD_PARAM;
return lustre_yaml_cb_helper(f, lookup_show_tbl,
show_rc, err_rc);
}
+
+int lustre_lnet_send_dbg_task(enum lnet_dbg_task dbg_task,
+ struct lnet_dbg_task_info *dbg_info,
+ struct cYAML **show_rc,
+ struct cYAML **err_rc)
+{
+ struct lnet_ioctl_dbg *dbg;
+ struct lnet_dbg_task_info *info;
+ int rc = LUSTRE_CFG_RC_NO_ERR;
+ char err_str[LNET_MAX_STR_LEN];
+
+ snprintf(err_str, sizeof(err_str), "\"success\"");
+
+ dbg = calloc(1, sizeof(*dbg) + sizeof(*info));
+ if (!dbg) {
+ snprintf(err_str, sizeof(err_str), "\"out of memory\"");
+ rc = LUSTRE_CFG_RC_OUT_OF_MEM;
+ goto out;
+ }
+
+ info = (struct lnet_dbg_task_info *)dbg->dbg_bulk;
+
+ LIBCFS_IOC_INIT_V2(*dbg, dbg_hdr);
+
+ dbg->dbg_task = dbg_task;
+ if (dbg_info)
+ memcpy(info, dbg_info, sizeof(*info));
+
+ rc = l_ioctl(LNET_DEV_ID, IOC_LIBCFS_DBG, dbg);
+ if (rc != 0) {
+ rc = -errno;
+ snprintf(err_str,
+ sizeof(err_str),
+ "\"debug task failed %s\"", strerror(errno));
+ goto out;
+ }
+
+out:
+ cYAML_build_error(rc, -1, DBG_CMD,
+ "debug", err_str, err_rc);
+
+ return rc;
+}
+
#define LUSTRE_CFG_RC_OUT_OF_RANGE_PARAM -3
#define LUSTRE_CFG_RC_OUT_OF_MEM -4
#define LUSTRE_CFG_RC_GENERIC_ERR -5
+#define LUSTRE_CFG_RC_NO_MATCH -6
+#define LUSTRE_CFG_RC_MATCH -7
+
+#include <lnet/lnet.h>
+#include <libcfs/libcfs_string.h>
+
+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;
+};
/* forward declaration of the cYAML structure. */
struct cYAML;
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.
*
struct cYAML **err_rc);
/*
- * lustre_lnet_config_net
- * Send down an IOCTL to configure a network.
+ * lustre_lnet_config_ni
+ * Send down an IOCTL to configure a network interface. It implicitly
+ * creates a network if one doesn't exist..
*
- * net - the network name
- * intf - the interface of the network of the form net_name(intf)
+ * 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
- * peer_to - peer timeout
- * peer_cr - peer credit
- * peer_buf_cr - peer buffer credits
- * - the above are LND tunable parameters and are optional
- * credits - network interface credits
- * smp - cpu affinity
+ * 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_net(char *net, char *intf, char *ip2net,
- int peer_to, int peer_cr, int peer_buf_cr,
- int credits, char *smp, int seq_no,
- struct lnet_ioctl_config_lnd_tunables *lnd_tunables,
- struct cYAML **err_rc);
+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_net
- * Send down an IOCTL to delete a network.
+ * 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 to delete.
+ * 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_net(char *nw, int seq_no,
- struct cYAML **err_rc);
+int lustre_lnet_del_ni(struct lnet_dlc_network_descr *nw,
+ int seq_no, struct cYAML **err_rc);
/*
* lustre_lnet_show_net
int lustre_yaml_show(char *f, struct cYAML **show_rc,
struct cYAML **err_rc);
+/*
+ * 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_send_dbg_task
+ * send a debug task to be carried out in the kernel. This API will
+ * not be exposed to the user through lnetctl utility. It can only be
+ * executed by being called directly.
+ * dbg_task: The task to be carried out
+ * dbg_info: task specific information
+ */
+int lustre_lnet_send_dbg_task(enum lnet_dbg_task dbg_task,
+ struct lnet_dbg_task_info *dbg_info,
+ struct cYAML **show_rc,
+ struct cYAML **err_rc);
+
#endif /* LIB_LNET_CONFIG_API_H */
* Author:
* James Simmons <jsimmons@infradead.org>
*/
+
+#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <libcfs/util/ioctl.h>
#include "cyaml.h"
static int
-lustre_ko2iblnd_show_net(struct cYAML *lndparams,
- struct lnet_ioctl_config_lnd_tunables *tunables)
+lustre_o2iblnd_show_tun(struct cYAML *lndparams,
+ struct lnet_ioctl_config_o2iblnd_tunables *lnd_cfg)
{
- struct lnet_ioctl_config_o2iblnd_tunables *lnd_cfg;
-
- lnd_cfg = &tunables->lt_tun_u.lt_o2ib;
-
if (cYAML_create_number(lndparams, "peercredits_hiw",
lnd_cfg->lnd_peercredits_hiw) == NULL)
- return -1;
+ return LUSTRE_CFG_RC_OUT_OF_MEM;
if (cYAML_create_number(lndparams, "map_on_demand",
lnd_cfg->lnd_map_on_demand) == NULL)
- return -1;
+ return LUSTRE_CFG_RC_OUT_OF_MEM;
if (cYAML_create_number(lndparams, "concurrent_sends",
lnd_cfg->lnd_concurrent_sends) == NULL)
- return -1;
+ return LUSTRE_CFG_RC_OUT_OF_MEM;
if (cYAML_create_number(lndparams, "fmr_pool_size",
lnd_cfg->lnd_fmr_pool_size) == NULL)
- return -1;
+ return LUSTRE_CFG_RC_OUT_OF_MEM;
if (cYAML_create_number(lndparams, "fmr_flush_trigger",
lnd_cfg->lnd_fmr_flush_trigger) == NULL)
- return -1;
+ return LUSTRE_CFG_RC_OUT_OF_MEM;
if (cYAML_create_number(lndparams, "fmr_cache",
lnd_cfg->lnd_fmr_cache) == NULL)
- return -1;
- return 0;
+ return LUSTRE_CFG_RC_OUT_OF_MEM;
+
+ return LUSTRE_CFG_RC_NO_ERR;
}
int
-lustre_interface_show_net(struct cYAML *interfaces, unsigned int index,
- bool detail, struct lnet_ioctl_config_data *data,
- struct lnet_ioctl_net_config *net_config)
+lustre_net_show_tunables(struct cYAML *tunables,
+ struct lnet_ioctl_config_lnd_cmn_tunables *cmn)
{
- char ni_index[2]; /* LNET_MAX_INTERFACES is only 16 */
-
- if (strlen(net_config->ni_interfaces[index]) == 0)
- return 0;
-
- snprintf(ni_index, sizeof(ni_index), "%d", index);
- if (cYAML_create_string(interfaces, ni_index,
- net_config->ni_interfaces[index]) == NULL)
- return -1;
-
- if (detail) {
- __u32 net = LNET_NETTYP(LNET_NIDNET(data->cfg_nid));
- struct lnet_ioctl_config_lnd_tunables *lnd_cfg;
- struct cYAML *lndparams;
-
- if (data->cfg_config_u.cfg_net.net_interface_count == 0 ||
- net != O2IBLND)
- return 0;
-
- lndparams = cYAML_create_object(interfaces, "lnd tunables");
- if (lndparams == NULL)
- return -1;
-
- lnd_cfg = (struct lnet_ioctl_config_lnd_tunables *)net_config->cfg_bulk;
- if (lustre_ko2iblnd_show_net(lndparams, lnd_cfg) < 0)
- return -1;
- }
- return 0;
+
+
+ if (cYAML_create_number(tunables, "peer_timeout",
+ cmn->lct_peer_timeout)
+ == NULL)
+ goto out;
+
+ if (cYAML_create_number(tunables, "peer_credits",
+ cmn->lct_peer_tx_credits)
+ == NULL)
+ goto out;
+
+ if (cYAML_create_number(tunables,
+ "peer_buffer_credits",
+ cmn->lct_peer_rtr_credits)
+ == NULL)
+ goto out;
+
+ if (cYAML_create_number(tunables, "credits",
+ cmn->lct_max_tx_credits)
+ == NULL)
+ goto out;
+
+ return LUSTRE_CFG_RC_NO_ERR;
+
+out:
+ return LUSTRE_CFG_RC_OUT_OF_MEM;
+}
+
+int
+lustre_ni_show_tunables(struct cYAML *lnd_tunables,
+ __u32 net_type,
+ struct lnet_lnd_tunables *lnd)
+{
+ int rc = LUSTRE_CFG_RC_NO_ERR;
+
+ if (net_type == O2IBLND)
+ rc = lustre_o2iblnd_show_tun(lnd_tunables,
+ &lnd->lnd_tun_u.lnd_o2ib);
+
+ return rc;
}
static void
-lustre_ko2iblnd_parse_net(struct cYAML *lndparams,
- struct lnet_ioctl_config_lnd_tunables *lnd_cfg)
+yaml_extract_o2ib_tun(struct cYAML *tree,
+ struct lnet_ioctl_config_o2iblnd_tunables *lnd_cfg)
{
struct cYAML *map_on_demand = NULL, *concurrent_sends = NULL;
struct cYAML *fmr_pool_size = NULL, *fmr_cache = NULL;
- struct cYAML *fmr_flush_trigger = NULL;
+ struct cYAML *fmr_flush_trigger = NULL, *lndparams = NULL;
+
+ lndparams = cYAML_get_object_item(tree, "lnd tunables");
+ if (!lndparams)
+ return;
map_on_demand = cYAML_get_object_item(lndparams, "map_on_demand");
- lnd_cfg->lt_tun_u.lt_o2ib.lnd_map_on_demand =
+ lnd_cfg->lnd_map_on_demand =
(map_on_demand) ? map_on_demand->cy_valueint : 0;
concurrent_sends = cYAML_get_object_item(lndparams, "concurrent_sends");
- lnd_cfg->lt_tun_u.lt_o2ib.lnd_concurrent_sends =
+ lnd_cfg->lnd_concurrent_sends =
(concurrent_sends) ? concurrent_sends->cy_valueint : 0;
fmr_pool_size = cYAML_get_object_item(lndparams, "fmr_pool_size");
- lnd_cfg->lt_tun_u.lt_o2ib.lnd_fmr_pool_size =
+ lnd_cfg->lnd_fmr_pool_size =
(fmr_pool_size) ? fmr_pool_size->cy_valueint : 0;
fmr_flush_trigger = cYAML_get_object_item(lndparams,
"fmr_flush_trigger");
- lnd_cfg->lt_tun_u.lt_o2ib.lnd_fmr_flush_trigger =
+ lnd_cfg->lnd_fmr_flush_trigger =
(fmr_flush_trigger) ? fmr_flush_trigger->cy_valueint : 0;
fmr_cache = cYAML_get_object_item(lndparams, "fmr_cache");
- lnd_cfg->lt_tun_u.lt_o2ib.lnd_fmr_cache =
+ lnd_cfg->lnd_fmr_cache =
(fmr_cache) ? fmr_cache->cy_valueint : 0;
}
+
void
-lustre_interface_parse(struct cYAML *lndparams, const char *dev_name,
- struct lnet_ioctl_config_lnd_tunables *lnd_cfg)
+lustre_yaml_extract_lnd_tunables(struct cYAML *tree,
+ __u32 net_type,
+ struct lnet_lnd_tunables *tun)
{
- if (dev_name != NULL && strstr(dev_name, "ib"))
- lustre_ko2iblnd_parse_net(lndparams, lnd_cfg);
+ if (net_type == O2IBLND)
+ yaml_extract_o2ib_tun(tree,
+ &tun->lnd_tun_u.lnd_o2ib);
+
}
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <limits.h>
#include <libcfs/util/ioctl.h>
#include <libcfs/util/parser.h>
#include <lnet/lnetctl.h>
+#include <lnet/nidstr.h>
#include "cyaml/cyaml.h"
#include "lnetconfig/liblnetconfig.h"
static int jt_config_lnet(int argc, char **argv);
static int jt_unconfig_lnet(int argc, char **argv);
static int jt_add_route(int argc, char **argv);
-static int jt_add_net(int argc, char **argv);
+static int jt_add_ni(int argc, char **argv);
static int jt_set_routing(int argc, char **argv);
static int jt_del_route(int argc, char **argv);
-static int jt_del_net(int argc, char **argv);
+static int jt_del_ni(int argc, char **argv);
static int jt_show_route(int argc, char **argv);
static int jt_show_net(int argc, char **argv);
static int jt_show_routing(int argc, char **argv);
};
command_t net_cmds[] = {
- {"add", jt_add_net, 0, "add a network\n"
+ {"add", jt_add_ni, 0, "add a network\n"
"\t--net: net name (e.g. tcp0)\n"
"\t--if: physical interface (e.g. eth0)\n"
"\t--ip2net: specify networks based on IP address patterns\n"
"\t--peer-buffer-credits: the number of buffer credits per peer\n"
"\t--credits: Network Interface credits\n"
"\t--cpt: CPU Partitions configured net uses (e.g. [0,1]\n"},
- {"del", jt_del_net, 0, "delete a network\n"
- "\t--net: net name (e.g. tcp0)\n"},
+ {"del", jt_del_ni, 0, "delete a network\n"
+ "\t--net: net name (e.g. tcp0)\n"
+ "\t--if: physical interface (e.g. eth0)\n"},
{"show", jt_show_net, 0, "show networks\n"
"\t--net: net name (e.g. tcp0) to filter on\n"
"\t--verbose: display detailed output per network\n"},
return rc;
}
-static int jt_add_net(int argc, char **argv)
+static int jt_add_ni(int argc, char **argv)
{
- char *network = NULL, *intf = NULL, *ip2net = NULL, *cpt = NULL;
+ char *ip2net = NULL;
long int pto = -1, pc = -1, pbc = -1, cre = -1;
struct cYAML *err_rc = NULL;
- int rc, opt;
+ int rc, opt, num_global_cpts = 0;
+ struct lnet_dlc_network_descr nw_descr;
+ struct cfs_expr_list *global_cpts = NULL;
+ struct lnet_ioctl_config_lnd_tunables tunables;
+ bool found = false;
+
+ memset(&tunables, 0, sizeof(tunables));
+ lustre_lnet_init_nw_descr(&nw_descr);
const char *const short_options = "n:i:p:t:c:b:r:s:h";
const struct option long_options[] = {
long_options, NULL)) != -1) {
switch (opt) {
case 'n':
- network = optarg;
+ nw_descr.nw_id = libcfs_str2net(optarg);
break;
case 'i':
- intf = optarg;
+ rc = lustre_lnet_parse_interfaces(optarg, &nw_descr);
+ if (rc != 0) {
+ cYAML_build_error(-1, -1, "ni", "add",
+ "bad interface list",
+ &err_rc);
+ goto failed;
+ }
break;
case 'p':
ip2net = optarg;
}
break;
case 's':
- cpt = optarg;
+ num_global_cpts =
+ cfs_expr_list_parse(optarg,
+ strlen(optarg),
+ 0, UINT_MAX, &global_cpts);
break;
case 'h':
print_help(net_cmds, "net", "add");
}
}
- rc = lustre_lnet_config_net(network, intf, ip2net, pto, pc, pbc,
- cre, cpt, -1, NULL, &err_rc);
+ if (pto > 0 || pc > 0 || pbc > 0 || cre > 0) {
+ tunables.lt_cmn.lct_peer_timeout = pto;
+ tunables.lt_cmn.lct_peer_tx_credits = pc;
+ tunables.lt_cmn.lct_peer_rtr_credits = pbc;
+ tunables.lt_cmn.lct_max_tx_credits = cre;
+ found = true;
+ }
+
+ rc = lustre_lnet_config_ni(&nw_descr,
+ (num_global_cpts > 0) ? global_cpts: NULL,
+ ip2net, (found) ? &tunables : NULL,
+ -1, &err_rc);
+
+ if (global_cpts != NULL)
+ cfs_expr_list_free(global_cpts);
+failed:
if (rc != LUSTRE_CFG_RC_NO_ERR)
cYAML_print_tree2file(stderr, err_rc);
return rc;
}
-static int jt_del_net(int argc, char **argv)
+static int jt_del_ni(int argc, char **argv)
{
- char *network = NULL;
struct cYAML *err_rc = NULL;
int rc, opt;
+ struct lnet_dlc_network_descr nw_descr;
+
+ lustre_lnet_init_nw_descr(&nw_descr);
- const char *const short_options = "n:h";
+ const char *const short_options = "n:i:h";
const struct option long_options[] = {
{ "net", 1, NULL, 'n' },
+ { "if", 1, NULL, 'i' },
{ "help", 0, NULL, 'h' },
{ NULL, 0, NULL, 0 },
};
long_options, NULL)) != -1) {
switch (opt) {
case 'n':
- network = optarg;
+ nw_descr.nw_id = libcfs_str2net(optarg);
+ break;
+ case 'i':
+ rc = lustre_lnet_parse_interfaces(optarg, &nw_descr);
+ if (rc != 0) {
+ cYAML_build_error(-1, -1, "ni", "add",
+ "bad interface list",
+ &err_rc);
+ goto out;
+ }
break;
case 'h':
print_help(net_cmds, "net", "del");
}
}
- rc = lustre_lnet_del_net(network, -1, &err_rc);
+ rc = lustre_lnet_del_ni(&nw_descr, -1, &err_rc);
+out:
if (rc != LUSTRE_CFG_RC_NO_ERR)
cYAML_print_tree2file(stderr, err_rc);