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