1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2
3 #include <linux/if_arp.h>
4 #include <linux/if_link.h>
5
6 #include "ipoib.h"
7 #include "networkd-network.h"
8 #include "parse-util.h"
9 #include "string-table.h"
10
11 assert_cc((int) IP_OVER_INFINIBAND_MODE_DATAGRAM == (int) IPOIB_MODE_DATAGRAM);
12 assert_cc((int) IP_OVER_INFINIBAND_MODE_CONNECTED == (int) IPOIB_MODE_CONNECTED);
13
netdev_ipoib_init(NetDev * netdev)14 static void netdev_ipoib_init(NetDev *netdev) {
15 IPoIB *ipoib;
16
17 assert(netdev);
18
19 ipoib = IPOIB(netdev);
20
21 assert(ipoib);
22
23 ipoib->mode = _IP_OVER_INFINIBAND_MODE_INVALID;
24 ipoib->umcast = -1;
25 }
26
netdev_ipoib_fill_message_create(NetDev * netdev,Link * link,sd_netlink_message * m)27 static int netdev_ipoib_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
28 IPoIB *ipoib;
29 int r;
30
31 assert(netdev);
32 assert(link);
33 assert(m);
34
35 ipoib = IPOIB(netdev);
36
37 assert(ipoib);
38
39 if (ipoib->pkey > 0) {
40 r = sd_netlink_message_append_u16(m, IFLA_IPOIB_PKEY, ipoib->pkey);
41 if (r < 0)
42 return r;
43 }
44
45 if (ipoib->mode >= 0) {
46 r = sd_netlink_message_append_u16(m, IFLA_IPOIB_MODE, ipoib->mode);
47 if (r < 0)
48 return r;
49 }
50
51 if (ipoib->umcast >= 0) {
52 r = sd_netlink_message_append_u16(m, IFLA_IPOIB_UMCAST, ipoib->umcast);
53 if (r < 0)
54 return r;
55 }
56
57 return 0;
58 }
59
ipoib_set_netlink_message(Link * link,sd_netlink_message * m)60 int ipoib_set_netlink_message(Link *link, sd_netlink_message *m) {
61 int r;
62
63 assert(link);
64 assert(link->network);
65 assert(m);
66
67 r = sd_netlink_message_set_flags(m, NLM_F_REQUEST | NLM_F_ACK);
68 if (r < 0)
69 return r;
70
71 r = sd_netlink_message_open_container(m, IFLA_LINKINFO);
72 if (r < 0)
73 return r;
74
75 r = sd_netlink_message_open_container_union(m, IFLA_INFO_DATA, link->kind);
76 if (r < 0)
77 return r;
78
79 if (link->network->ipoib_mode >= 0) {
80 r = sd_netlink_message_append_u16(m, IFLA_IPOIB_MODE, link->network->ipoib_mode);
81 if (r < 0)
82 return r;
83 }
84
85 if (link->network->ipoib_umcast >= 0) {
86 r = sd_netlink_message_append_u16(m, IFLA_IPOIB_UMCAST, link->network->ipoib_umcast);
87 if (r < 0)
88 return r;
89 }
90
91 r = sd_netlink_message_close_container(m);
92 if (r < 0)
93 return r;
94
95 r = sd_netlink_message_close_container(m);
96 if (r < 0)
97 return r;
98
99 return 0;
100 }
101
102 static const char * const ipoib_mode_table[_IP_OVER_INFINIBAND_MODE_MAX] = {
103 [IP_OVER_INFINIBAND_MODE_DATAGRAM] = "datagram",
104 [IP_OVER_INFINIBAND_MODE_CONNECTED] = "connected",
105 };
106
107 DEFINE_PRIVATE_STRING_TABLE_LOOKUP_FROM_STRING(ipoib_mode, IPoIBMode);
108 DEFINE_CONFIG_PARSE_ENUM(config_parse_ipoib_mode, ipoib_mode, IPoIBMode, "Failed to parse IPoIB mode");
109
config_parse_ipoib_pkey(const char * unit,const char * filename,unsigned line,const char * section,unsigned section_line,const char * lvalue,int ltype,const char * rvalue,void * data,void * userdata)110 int config_parse_ipoib_pkey(
111 const char *unit,
112 const char *filename,
113 unsigned line,
114 const char *section,
115 unsigned section_line,
116 const char *lvalue,
117 int ltype,
118 const char *rvalue,
119 void *data,
120 void *userdata) {
121
122 uint16_t u, *pkey = data;
123 int r;
124
125 assert(filename);
126 assert(lvalue);
127 assert(rvalue);
128 assert(data);
129
130 if (isempty(rvalue)) {
131 *pkey = 0; /* 0 means unset. */
132 return 0;
133 }
134
135 r = safe_atou16(rvalue, &u);
136 if (r < 0) {
137 log_syntax(unit, LOG_WARNING, filename, line, r,
138 "Failed to parse IPoIB pkey '%s', ignoring assignment: %m",
139 rvalue);
140 return 0;
141 }
142 if (IN_SET(u, 0, 0x8000)) {
143 log_syntax(unit, LOG_WARNING, filename, line, 0,
144 "IPoIB pkey cannot be 0 nor 0x8000, ignoring assignment: %s",
145 rvalue);
146 return 0;
147 }
148
149 *pkey = u;
150 return 0;
151 }
152
153
154 const NetDevVTable ipoib_vtable = {
155 .object_size = sizeof(IPoIB),
156 .sections = NETDEV_COMMON_SECTIONS "IPoIB\0",
157 .init = netdev_ipoib_init,
158 .fill_message_create = netdev_ipoib_fill_message_create,
159 .create_type = NETDEV_CREATE_STACKED,
160 .iftype = ARPHRD_INFINIBAND,
161 .generate_mac = true,
162 };
163