Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net/smc: add support for user defined EIDs

SMC-Dv2 allows users to define EIDs which allows to create separate
name spaces enabling users to cluster their SMC-Dv2 connections.
Add support for user defined EIDs and extent the generic netlink
interface so users can add, remove and dump EIDs.

Signed-off-by: Karsten Graul <kgraul@linux.ibm.com>
Reviewed-by: Guvenc Gulce <guvenc@linux.ibm.com>
Signed-off-by: Guvenc Gulce <guvenc@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Karsten Graul and committed by
David S. Miller
fa086662 f787e3cf

+335 -31
+15
include/uapi/linux/smc.h
··· 38 38 #define SMC_GENL_FAMILY_VERSION 1 39 39 40 40 #define SMC_PCI_ID_STR_LEN 16 /* Max length of pci id string */ 41 + #define SMC_MAX_HOSTNAME_LEN 32 /* Max length of the hostname */ 42 + #define SMC_MAX_UEID 4 /* Max number of user EIDs */ 43 + #define SMC_MAX_EID_LEN 32 /* Max length of an EID */ 41 44 42 45 /* SMC_GENL_FAMILY commands */ 43 46 enum { ··· 52 49 SMC_NETLINK_GET_DEV_SMCR, 53 50 SMC_NETLINK_GET_STATS, 54 51 SMC_NETLINK_GET_FBACK_STATS, 52 + SMC_NETLINK_DUMP_UEID, 53 + SMC_NETLINK_ADD_UEID, 54 + SMC_NETLINK_REMOVE_UEID, 55 + SMC_NETLINK_FLUSH_UEID, 55 56 }; 56 57 57 58 /* SMC_GENL_FAMILY top level attributes */ ··· 248 241 SMC_NLA_FBACK_STATS_RSN_CNT, /* u16 */ 249 242 __SMC_NLA_FBACK_STATS_MAX, 250 243 SMC_NLA_FBACK_STATS_MAX = __SMC_NLA_FBACK_STATS_MAX - 1 244 + }; 245 + 246 + /* SMC_NETLINK_UEID attributes */ 247 + enum { 248 + SMC_NLA_EID_TABLE_UNSPEC, 249 + SMC_NLA_EID_TABLE_ENTRY, /* string */ 250 + __SMC_NLA_EID_TABLE_MAX, 251 + SMC_NLA_EID_TABLE_MAX = __SMC_NLA_EID_TABLE_MAX - 1 251 252 }; 252 253 #endif /* _UAPI_LINUX_SMC_H */
+22 -12
net/smc/af_smc.c
··· 829 829 smc_rmb_sync_sg_for_device(&smc->conn); 830 830 831 831 reason_code = smc_clc_send_confirm(smc, ini->first_contact_local, 832 - SMC_V1); 832 + SMC_V1, NULL); 833 833 if (reason_code) 834 834 goto connect_abort; 835 835 ··· 883 883 struct smc_clc_msg_accept_confirm *aclc, 884 884 struct smc_init_info *ini) 885 885 { 886 + u8 *eid = NULL; 886 887 int rc = 0; 887 888 888 889 ini->is_smcd = true; ··· 919 918 smc_rx_init(smc); 920 919 smc_tx_init(smc); 921 920 921 + if (aclc->hdr.version > SMC_V1) { 922 + struct smc_clc_msg_accept_confirm_v2 *clc_v2 = 923 + (struct smc_clc_msg_accept_confirm_v2 *)aclc; 924 + 925 + eid = clc_v2->eid; 926 + } 927 + 922 928 rc = smc_clc_send_confirm(smc, ini->first_contact_local, 923 - aclc->hdr.version); 929 + aclc->hdr.version, eid); 924 930 if (rc) 925 931 goto connect_abort; 926 932 mutex_unlock(&smc_server_lgr_pending); ··· 1541 1533 pclc_smcd = smc_get_clc_msg_smcd(pclc); 1542 1534 smc_v2_ext = smc_get_clc_v2_ext(pclc); 1543 1535 smcd_v2_ext = smc_get_clc_smcd_v2_ext(smc_v2_ext); 1544 - if (!smcd_v2_ext || 1545 - !smc_v2_ext->hdr.flag.seid) { /* no system EID support for SMCD */ 1546 - smc_find_ism_store_rc(SMC_CLC_DECL_NOSEID, ini); 1536 + if (!smcd_v2_ext) { 1537 + smc_find_ism_store_rc(SMC_CLC_DECL_NOV2DEXT, ini); 1547 1538 goto not_found; 1548 1539 } 1549 1540 ··· 1562 1555 } 1563 1556 mutex_unlock(&smcd_dev_list.mutex); 1564 1557 1565 - if (ini->ism_dev[0]) { 1566 - smc_ism_get_system_eid(ini->ism_dev[0], &eid); 1567 - if (memcmp(eid, smcd_v2_ext->system_eid, SMC_MAX_EID_LEN)) 1568 - goto not_found; 1569 - } else { 1558 + if (!ini->ism_dev[0]) 1570 1559 goto not_found; 1571 - } 1560 + 1561 + smc_ism_get_system_eid(ini->ism_dev[0], &eid); 1562 + if (!smc_clc_match_eid(ini->negotiated_eid, smc_v2_ext, 1563 + smcd_v2_ext->system_eid, eid)) 1564 + goto not_found; 1572 1565 1573 1566 /* separate - outside the smcd_dev_list.lock */ 1574 1567 smcd_version = ini->smcd_version; ··· 1586 1579 } 1587 1580 /* no V2 ISM device could be initialized */ 1588 1581 ini->smcd_version = smcd_version; /* restore original value */ 1582 + ini->negotiated_eid[0] = 0; 1589 1583 1590 1584 not_found: 1591 1585 ini->smcd_version &= ~SMC_V2; ··· 1796 1788 1797 1789 /* send SMC Accept CLC message */ 1798 1790 rc = smc_clc_send_accept(new_smc, ini->first_contact_local, 1799 - ini->smcd_version == SMC_V2 ? SMC_V2 : SMC_V1); 1791 + ini->smcd_version == SMC_V2 ? SMC_V2 : SMC_V1, 1792 + ini->negotiated_eid); 1800 1793 if (rc) 1801 1794 goto out_unlock; 1802 1795 ··· 2671 2662 proto_unregister(&smc_proto); 2672 2663 smc_pnet_exit(); 2673 2664 smc_nl_exit(); 2665 + smc_clc_exit(); 2674 2666 unregister_pernet_subsys(&smc_net_stat_ops); 2675 2667 unregister_pernet_subsys(&smc_net_ops); 2676 2668 rcu_barrier();
-3
net/smc/smc.h
··· 29 29 * devices 30 30 */ 31 31 32 - #define SMC_MAX_HOSTNAME_LEN 32 33 - #define SMC_MAX_EID_LEN 32 34 - 35 32 extern struct proto smc_proto; 36 33 extern struct proto smc_proto6; 37 34
+250 -13
net/smc/smc_clc.c
··· 26 26 #include "smc_clc.h" 27 27 #include "smc_ib.h" 28 28 #include "smc_ism.h" 29 + #include "smc_netlink.h" 29 30 30 31 #define SMCR_CLC_ACCEPT_CONFIRM_LEN 68 31 32 #define SMCD_CLC_ACCEPT_CONFIRM_LEN 48 ··· 39 38 static const char SMCD_EYECATCHER[4] = {'\xe2', '\xd4', '\xc3', '\xc4'}; 40 39 41 40 static u8 smc_hostname[SMC_MAX_HOSTNAME_LEN]; 41 + 42 + struct smc_clc_eid_table { 43 + rwlock_t lock; 44 + struct list_head list; 45 + u8 ueid_cnt; 46 + u8 seid_enabled; 47 + }; 48 + 49 + static struct smc_clc_eid_table smc_clc_eid_table; 50 + 51 + struct smc_clc_eid_entry { 52 + struct list_head list; 53 + u8 eid[SMC_MAX_EID_LEN]; 54 + }; 55 + 56 + /* The size of a user EID is 32 characters. 57 + * Valid characters should be (single-byte character set) A-Z, 0-9, '.' and '-'. 58 + * Blanks should only be used to pad to the expected size. 59 + * First character must be alphanumeric. 60 + */ 61 + static bool smc_clc_ueid_valid(char *ueid) 62 + { 63 + char *end = ueid + SMC_MAX_EID_LEN; 64 + 65 + while (--end >= ueid && isspace(*end)) 66 + ; 67 + if (end < ueid) 68 + return false; 69 + if (!isalnum(*ueid) || islower(*ueid)) 70 + return false; 71 + while (ueid <= end) { 72 + if ((!isalnum(*ueid) || islower(*ueid)) && *ueid != '.' && 73 + *ueid != '-') 74 + return false; 75 + ueid++; 76 + } 77 + return true; 78 + } 79 + 80 + static int smc_clc_ueid_add(char *ueid) 81 + { 82 + struct smc_clc_eid_entry *new_ueid, *tmp_ueid; 83 + int rc; 84 + 85 + if (!smc_clc_ueid_valid(ueid)) 86 + return -EINVAL; 87 + 88 + /* add a new ueid entry to the ueid table if there isn't one */ 89 + new_ueid = kzalloc(sizeof(*new_ueid), GFP_KERNEL); 90 + if (!new_ueid) 91 + return -ENOMEM; 92 + memcpy(new_ueid->eid, ueid, SMC_MAX_EID_LEN); 93 + 94 + write_lock(&smc_clc_eid_table.lock); 95 + if (smc_clc_eid_table.ueid_cnt >= SMC_MAX_UEID) { 96 + rc = -ERANGE; 97 + goto err_out; 98 + } 99 + list_for_each_entry(tmp_ueid, &smc_clc_eid_table.list, list) { 100 + if (!memcmp(tmp_ueid->eid, ueid, SMC_MAX_EID_LEN)) { 101 + rc = -EEXIST; 102 + goto err_out; 103 + } 104 + } 105 + list_add_tail(&new_ueid->list, &smc_clc_eid_table.list); 106 + smc_clc_eid_table.ueid_cnt++; 107 + write_unlock(&smc_clc_eid_table.lock); 108 + return 0; 109 + 110 + err_out: 111 + write_unlock(&smc_clc_eid_table.lock); 112 + kfree(new_ueid); 113 + return rc; 114 + } 115 + 116 + int smc_nl_add_ueid(struct sk_buff *skb, struct genl_info *info) 117 + { 118 + struct nlattr *nla_ueid = info->attrs[SMC_NLA_EID_TABLE_ENTRY]; 119 + char *ueid; 120 + 121 + if (!nla_ueid || nla_len(nla_ueid) != SMC_MAX_EID_LEN + 1) 122 + return -EINVAL; 123 + ueid = (char *)nla_data(nla_ueid); 124 + 125 + return smc_clc_ueid_add(ueid); 126 + } 127 + 128 + /* remove one or all ueid entries from the table */ 129 + static int smc_clc_ueid_remove(char *ueid) 130 + { 131 + struct smc_clc_eid_entry *lst_ueid, *tmp_ueid; 132 + int rc = -ENOENT; 133 + 134 + /* remove table entry */ 135 + write_lock(&smc_clc_eid_table.lock); 136 + list_for_each_entry_safe(lst_ueid, tmp_ueid, &smc_clc_eid_table.list, 137 + list) { 138 + if (!ueid || !memcmp(lst_ueid->eid, ueid, SMC_MAX_EID_LEN)) { 139 + list_del(&lst_ueid->list); 140 + smc_clc_eid_table.ueid_cnt--; 141 + kfree(lst_ueid); 142 + rc = 0; 143 + } 144 + } 145 + write_unlock(&smc_clc_eid_table.lock); 146 + return rc; 147 + } 148 + 149 + int smc_nl_remove_ueid(struct sk_buff *skb, struct genl_info *info) 150 + { 151 + struct nlattr *nla_ueid = info->attrs[SMC_NLA_EID_TABLE_ENTRY]; 152 + char *ueid; 153 + 154 + if (!nla_ueid || nla_len(nla_ueid) != SMC_MAX_EID_LEN + 1) 155 + return -EINVAL; 156 + ueid = (char *)nla_data(nla_ueid); 157 + 158 + return smc_clc_ueid_remove(ueid); 159 + } 160 + 161 + int smc_nl_flush_ueid(struct sk_buff *skb, struct genl_info *info) 162 + { 163 + smc_clc_ueid_remove(NULL); 164 + return 0; 165 + } 166 + 167 + static int smc_nl_ueid_dumpinfo(struct sk_buff *skb, u32 portid, u32 seq, 168 + u32 flags, char *ueid) 169 + { 170 + char ueid_str[SMC_MAX_EID_LEN + 1]; 171 + void *hdr; 172 + 173 + hdr = genlmsg_put(skb, portid, seq, &smc_gen_nl_family, 174 + flags, SMC_NETLINK_DUMP_UEID); 175 + if (!hdr) 176 + return -ENOMEM; 177 + snprintf(ueid_str, sizeof(ueid_str), "%s", ueid); 178 + if (nla_put_string(skb, SMC_NLA_EID_TABLE_ENTRY, ueid_str)) { 179 + genlmsg_cancel(skb, hdr); 180 + return -EMSGSIZE; 181 + } 182 + genlmsg_end(skb, hdr); 183 + return 0; 184 + } 185 + 186 + static int _smc_nl_ueid_dump(struct sk_buff *skb, u32 portid, u32 seq, 187 + int start_idx) 188 + { 189 + struct smc_clc_eid_entry *lst_ueid; 190 + int idx = 0; 191 + 192 + read_lock(&smc_clc_eid_table.lock); 193 + list_for_each_entry(lst_ueid, &smc_clc_eid_table.list, list) { 194 + if (idx++ < start_idx) 195 + continue; 196 + if (smc_nl_ueid_dumpinfo(skb, portid, seq, NLM_F_MULTI, 197 + lst_ueid->eid)) { 198 + --idx; 199 + break; 200 + } 201 + } 202 + read_unlock(&smc_clc_eid_table.lock); 203 + return idx; 204 + } 205 + 206 + int smc_nl_dump_ueid(struct sk_buff *skb, struct netlink_callback *cb) 207 + { 208 + struct smc_nl_dmp_ctx *cb_ctx = smc_nl_dmp_ctx(cb); 209 + int idx; 210 + 211 + idx = _smc_nl_ueid_dump(skb, NETLINK_CB(cb->skb).portid, 212 + cb->nlh->nlmsg_seq, cb_ctx->pos[0]); 213 + 214 + cb_ctx->pos[0] = idx; 215 + return skb->len; 216 + } 217 + 218 + static bool _smc_clc_match_ueid(u8 *peer_ueid) 219 + { 220 + struct smc_clc_eid_entry *tmp_ueid; 221 + 222 + list_for_each_entry(tmp_ueid, &smc_clc_eid_table.list, list) { 223 + if (!memcmp(tmp_ueid->eid, peer_ueid, SMC_MAX_EID_LEN)) 224 + return true; 225 + } 226 + return false; 227 + } 228 + 229 + bool smc_clc_match_eid(u8 *negotiated_eid, 230 + struct smc_clc_v2_extension *smc_v2_ext, 231 + u8 *peer_eid, u8 *local_eid) 232 + { 233 + bool match = false; 234 + int i; 235 + 236 + negotiated_eid[0] = 0; 237 + read_lock(&smc_clc_eid_table.lock); 238 + if (smc_clc_eid_table.seid_enabled && 239 + smc_v2_ext->hdr.flag.seid && 240 + !memcmp(peer_eid, local_eid, SMC_MAX_EID_LEN)) { 241 + memcpy(negotiated_eid, peer_eid, SMC_MAX_EID_LEN); 242 + match = true; 243 + goto out; 244 + } 245 + 246 + for (i = 0; i < smc_v2_ext->hdr.eid_cnt; i++) { 247 + if (_smc_clc_match_ueid(smc_v2_ext->user_eids[i])) { 248 + memcpy(negotiated_eid, smc_v2_ext->user_eids[i], 249 + SMC_MAX_EID_LEN); 250 + match = true; 251 + goto out; 252 + } 253 + } 254 + out: 255 + read_unlock(&smc_clc_eid_table.lock); 256 + return match; 257 + } 42 258 43 259 /* check arriving CLC proposal */ 44 260 static bool smc_clc_msg_prop_valid(struct smc_clc_msg_proposal *pclc) ··· 768 550 if (ini->smc_type_v2 == SMC_TYPE_N) { 769 551 pclc_smcd->v2_ext_offset = 0; 770 552 } else { 553 + struct smc_clc_eid_entry *ueident; 771 554 u16 v2_ext_offset; 772 555 u8 *eid = NULL; 773 556 ··· 779 560 pclc_prfx->ipv6_prefixes_cnt * 780 561 sizeof(ipv6_prfx[0]); 781 562 pclc_smcd->v2_ext_offset = htons(v2_ext_offset); 782 - v2_ext->hdr.eid_cnt = 0; 563 + 564 + read_lock(&smc_clc_eid_table.lock); 565 + v2_ext->hdr.eid_cnt = smc_clc_eid_table.ueid_cnt; 566 + plen += smc_clc_eid_table.ueid_cnt * SMC_MAX_EID_LEN; 567 + i = 0; 568 + list_for_each_entry(ueident, &smc_clc_eid_table.list, list) { 569 + memcpy(v2_ext->user_eids[i++], ueident->eid, 570 + sizeof(ueident->eid)); 571 + } 572 + v2_ext->hdr.flag.seid = smc_clc_eid_table.seid_enabled; 573 + read_unlock(&smc_clc_eid_table.lock); 783 574 v2_ext->hdr.ism_gid_cnt = ini->ism_offered_cnt; 784 575 v2_ext->hdr.flag.release = SMC_RELEASE; 785 - v2_ext->hdr.flag.seid = 1; 786 576 v2_ext->hdr.smcd_v2_ext_offset = htons(sizeof(*v2_ext) - 787 577 offsetofend(struct smc_clnt_opts_area_hdr, 788 578 smcd_v2_ext_offset) + ··· 800 572 smc_ism_get_system_eid(ini->ism_dev[0], &eid); 801 573 else 802 574 smc_ism_get_system_eid(ini->ism_dev[1], &eid); 803 - if (eid) 575 + if (eid && v2_ext->hdr.flag.seid) 804 576 memcpy(smcd_v2_ext->system_eid, eid, SMC_MAX_EID_LEN); 805 577 plen += sizeof(*v2_ext) + sizeof(*smcd_v2_ext); 806 578 if (ini->ism_offered_cnt) { ··· 835 607 } 836 608 if (ini->smc_type_v2 != SMC_TYPE_N) { 837 609 vec[i].iov_base = v2_ext; 838 - vec[i++].iov_len = sizeof(*v2_ext); 610 + vec[i++].iov_len = sizeof(*v2_ext) + 611 + (v2_ext->hdr.eid_cnt * SMC_MAX_EID_LEN); 839 612 vec[i].iov_base = smcd_v2_ext; 840 613 vec[i++].iov_len = sizeof(*smcd_v2_ext); 841 614 if (ini->ism_offered_cnt) { ··· 864 635 /* build and send CLC CONFIRM / ACCEPT message */ 865 636 static int smc_clc_send_confirm_accept(struct smc_sock *smc, 866 637 struct smc_clc_msg_accept_confirm_v2 *clc_v2, 867 - int first_contact, u8 version) 638 + int first_contact, u8 version, 639 + u8 *eid) 868 640 { 869 641 struct smc_connection *conn = &smc->conn; 870 642 struct smc_clc_msg_accept_confirm *clc; ··· 893 663 if (version == SMC_V1) { 894 664 clc->hdr.length = htons(SMCD_CLC_ACCEPT_CONFIRM_LEN); 895 665 } else { 896 - u8 *eid = NULL; 897 - 898 666 clc_v2->chid = htons(smc_ism_get_chid(conn->lgr->smcd)); 899 - smc_ism_get_system_eid(conn->lgr->smcd, &eid); 900 - if (eid) 667 + if (eid[0]) 901 668 memcpy(clc_v2->eid, eid, SMC_MAX_EID_LEN); 902 669 len = SMCD_CLC_ACCEPT_CONFIRM_LEN_V2; 903 670 if (first_contact) ··· 959 732 960 733 /* send CLC CONFIRM message across internal TCP socket */ 961 734 int smc_clc_send_confirm(struct smc_sock *smc, bool clnt_first_contact, 962 - u8 version) 735 + u8 version, u8 *eid) 963 736 { 964 737 struct smc_clc_msg_accept_confirm_v2 cclc_v2; 965 738 int reason_code = 0; ··· 969 742 memset(&cclc_v2, 0, sizeof(cclc_v2)); 970 743 cclc_v2.hdr.type = SMC_CLC_CONFIRM; 971 744 len = smc_clc_send_confirm_accept(smc, &cclc_v2, clnt_first_contact, 972 - version); 745 + version, eid); 973 746 if (len < ntohs(cclc_v2.hdr.length)) { 974 747 if (len >= 0) { 975 748 reason_code = -ENETUNREACH; ··· 984 757 985 758 /* send CLC ACCEPT message across internal TCP socket */ 986 759 int smc_clc_send_accept(struct smc_sock *new_smc, bool srv_first_contact, 987 - u8 version) 760 + u8 version, u8 *negotiated_eid) 988 761 { 989 762 struct smc_clc_msg_accept_confirm_v2 aclc_v2; 990 763 int len; ··· 992 765 memset(&aclc_v2, 0, sizeof(aclc_v2)); 993 766 aclc_v2.hdr.type = SMC_CLC_ACCEPT; 994 767 len = smc_clc_send_confirm_accept(new_smc, &aclc_v2, srv_first_contact, 995 - version); 768 + version, negotiated_eid); 996 769 if (len < ntohs(aclc_v2.hdr.length)) 997 770 len = len >= 0 ? -EPROTO : -new_smc->clcsock->sk->sk_err; 998 771 ··· 1012 785 u = utsname(); 1013 786 memcpy(smc_hostname, u->nodename, 1014 787 min_t(size_t, strlen(u->nodename), sizeof(smc_hostname))); 788 + 789 + INIT_LIST_HEAD(&smc_clc_eid_table.list); 790 + rwlock_init(&smc_clc_eid_table.lock); 791 + smc_clc_eid_table.ueid_cnt = 0; 792 + smc_clc_eid_table.seid_enabled = 1; 793 + } 794 + 795 + void smc_clc_exit(void) 796 + { 797 + smc_clc_ueid_remove(NULL); 1015 798 }
+14 -2
net/smc/smc_clc.h
··· 14 14 #define _SMC_CLC_H 15 15 16 16 #include <rdma/ib_verbs.h> 17 + #include <linux/smc.h> 17 18 18 19 #include "smc.h" 20 + #include "smc_netlink.h" 19 21 20 22 #define SMC_CLC_PROPOSAL 0x01 21 23 #define SMC_CLC_ACCEPT 0x02 ··· 160 158 } __aligned(4); 161 159 162 160 #define SMC_CLC_MAX_V6_PREFIX 8 161 + #define SMC_CLC_MAX_UEID 8 163 162 164 163 struct smc_clc_msg_proposal_area { 165 164 struct smc_clc_msg_proposal pclc_base; ··· 168 165 struct smc_clc_msg_proposal_prefix pclc_prfx; 169 166 struct smc_clc_ipv6_prefix pclc_prfx_ipv6[SMC_CLC_MAX_V6_PREFIX]; 170 167 struct smc_clc_v2_extension pclc_v2_ext; 168 + u8 user_eids[SMC_CLC_MAX_UEID][SMC_MAX_EID_LEN]; 171 169 struct smc_clc_smcd_v2_extension pclc_smcd_v2_ext; 172 170 struct smc_clc_smcd_gid_chid pclc_gidchids[SMC_MAX_ISM_DEVS]; 173 171 struct smc_clc_msg_trail pclc_trl; ··· 334 330 int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info, u8 version); 335 331 int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini); 336 332 int smc_clc_send_confirm(struct smc_sock *smc, bool clnt_first_contact, 337 - u8 version); 333 + u8 version, u8 *eid); 338 334 int smc_clc_send_accept(struct smc_sock *smc, bool srv_first_contact, 339 - u8 version); 335 + u8 version, u8 *negotiated_eid); 340 336 void smc_clc_init(void) __init; 337 + void smc_clc_exit(void); 341 338 void smc_clc_get_hostname(u8 **host); 339 + bool smc_clc_match_eid(u8 *negotiated_eid, 340 + struct smc_clc_v2_extension *smc_v2_ext, 341 + u8 *peer_eid, u8 *local_eid); 342 + int smc_nl_dump_ueid(struct sk_buff *skb, struct netlink_callback *cb); 343 + int smc_nl_add_ueid(struct sk_buff *skb, struct genl_info *info); 344 + int smc_nl_remove_ueid(struct sk_buff *skb, struct genl_info *info); 345 + int smc_nl_flush_ueid(struct sk_buff *skb, struct genl_info *info); 342 346 343 347 #endif
+1
net/smc/smc_core.h
··· 310 310 u8 first_contact_local; 311 311 unsigned short vlan_id; 312 312 u32 rc; 313 + u8 negotiated_eid[SMC_MAX_EID_LEN]; 313 314 /* SMC-R */ 314 315 struct smc_clc_msg_local *ib_lcl; 315 316 struct smc_ib_device *ib_dev;
+31 -1
net/smc/smc_netlink.c
··· 19 19 #include "smc_core.h" 20 20 #include "smc_ism.h" 21 21 #include "smc_ib.h" 22 + #include "smc_clc.h" 22 23 #include "smc_stats.h" 23 24 #include "smc_netlink.h" 24 25 25 - #define SMC_CMD_MAX_ATTR 1 26 + const struct nla_policy 27 + smc_gen_ueid_policy[SMC_NLA_EID_TABLE_MAX + 1] = { 28 + [SMC_NLA_EID_TABLE_UNSPEC] = { .type = NLA_UNSPEC }, 29 + [SMC_NLA_EID_TABLE_ENTRY] = { .type = NLA_STRING, 30 + .len = SMC_MAX_EID_LEN, 31 + }, 32 + }; 26 33 34 + #define SMC_CMD_MAX_ATTR 1 27 35 /* SMC_GENL generic netlink operation definition */ 28 36 static const struct genl_ops smc_gen_nl_ops[] = { 29 37 { ··· 73 65 .cmd = SMC_NETLINK_GET_FBACK_STATS, 74 66 /* can be retrieved by unprivileged users */ 75 67 .dumpit = smc_nl_get_fback_stats, 68 + }, 69 + { 70 + .cmd = SMC_NETLINK_DUMP_UEID, 71 + /* can be retrieved by unprivileged users */ 72 + .dumpit = smc_nl_dump_ueid, 73 + }, 74 + { 75 + .cmd = SMC_NETLINK_ADD_UEID, 76 + .flags = GENL_ADMIN_PERM, 77 + .doit = smc_nl_add_ueid, 78 + .policy = smc_gen_ueid_policy, 79 + }, 80 + { 81 + .cmd = SMC_NETLINK_REMOVE_UEID, 82 + .flags = GENL_ADMIN_PERM, 83 + .doit = smc_nl_remove_ueid, 84 + .policy = smc_gen_ueid_policy, 85 + }, 86 + { 87 + .cmd = SMC_NETLINK_FLUSH_UEID, 88 + .flags = GENL_ADMIN_PERM, 89 + .doit = smc_nl_flush_ueid, 76 90 }, 77 91 }; 78 92
+2
net/smc/smc_netlink.h
··· 17 17 18 18 extern struct genl_family smc_gen_nl_family; 19 19 20 + extern const struct nla_policy smc_gen_ueid_policy[]; 21 + 20 22 struct smc_nl_dmp_ctx { 21 23 int pos[3]; 22 24 };