[infiniband] Allow for the creation of multicast groups
[ipxe.git] / src / net / netdev_settings.c
1 /*
2 * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26 #include <string.h>
27 #include <errno.h>
28 #include <byteswap.h>
29 #include <ipxe/dhcp.h>
30 #include <ipxe/dhcpopts.h>
31 #include <ipxe/settings.h>
32 #include <ipxe/device.h>
33 #include <ipxe/netdevice.h>
34 #include <ipxe/init.h>
35
36 /** @file
37 *
38 * Network device configuration settings
39 *
40 */
41
42 /** Network device predefined settings */
43 const struct setting mac_setting __setting ( SETTING_NETDEV, mac ) = {
44 .name = "mac",
45 .description = "MAC address",
46 .type = &setting_type_hex,
47 };
48 const struct setting bustype_setting __setting ( SETTING_NETDEV, bustype ) = {
49 .name = "bustype",
50 .description = "Bus type",
51 .type = &setting_type_string,
52 };
53 const struct setting busloc_setting __setting ( SETTING_NETDEV, busloc ) = {
54 .name = "busloc",
55 .description = "Bus location",
56 .type = &setting_type_uint32,
57 };
58 const struct setting busid_setting __setting ( SETTING_NETDEV, busid ) = {
59 .name = "busid",
60 .description = "Bus ID",
61 .type = &setting_type_hex,
62 };
63 const struct setting chip_setting __setting ( SETTING_NETDEV, chip ) = {
64 .name = "chip",
65 .description = "Chip",
66 .type = &setting_type_string,
67 };
68 const struct setting ifname_setting __setting ( SETTING_NETDEV, ifname ) = {
69 .name = "ifname",
70 .description = "Interface name",
71 .type = &setting_type_string,
72 };
73
74 /**
75 * Store MAC address setting
76 *
77 * @v netdev Network device
78 * @v data Setting data, or NULL to clear setting
79 * @v len Length of setting data
80 * @ret rc Return status code
81 */
82 static int netdev_store_mac ( struct net_device *netdev,
83 const void *data, size_t len ) {
84 struct ll_protocol *ll_protocol = netdev->ll_protocol;
85
86 /* Record new MAC address */
87 if ( data ) {
88 if ( len != netdev->ll_protocol->ll_addr_len )
89 return -EINVAL;
90 memcpy ( netdev->ll_addr, data, len );
91 } else {
92 /* Reset MAC address if clearing setting */
93 ll_protocol->init_addr ( netdev->hw_addr, netdev->ll_addr );
94 }
95
96 return 0;
97 }
98
99 /**
100 * Fetch MAC address setting
101 *
102 * @v netdev Network device
103 * @v data Buffer to fill with setting data
104 * @v len Length of buffer
105 * @ret len Length of setting data, or negative error
106 */
107 static int netdev_fetch_mac ( struct net_device *netdev, void *data,
108 size_t len ) {
109
110 if ( len > netdev->ll_protocol->ll_addr_len )
111 len = netdev->ll_protocol->ll_addr_len;
112 memcpy ( data, netdev->ll_addr, len );
113 return netdev->ll_protocol->ll_addr_len;
114 }
115
116 /**
117 * Fetch bus type setting
118 *
119 * @v netdev Network device
120 * @v data Buffer to fill with setting data
121 * @v len Length of buffer
122 * @ret len Length of setting data, or negative error
123 */
124 static int netdev_fetch_bustype ( struct net_device *netdev, void *data,
125 size_t len ) {
126 static const char *bustypes[] = {
127 [BUS_TYPE_PCI] = "PCI",
128 [BUS_TYPE_ISAPNP] = "ISAPNP",
129 [BUS_TYPE_EISA] = "EISA",
130 [BUS_TYPE_MCA] = "MCA",
131 [BUS_TYPE_ISA] = "ISA",
132 [BUS_TYPE_TAP] = "TAP",
133 [BUS_TYPE_EFI] = "EFI",
134 [BUS_TYPE_XEN] = "XEN",
135 [BUS_TYPE_HV] = "HV",
136 [BUS_TYPE_USB] = "USB",
137 };
138 struct device_description *desc = &netdev->dev->desc;
139 const char *bustype;
140
141 assert ( desc->bus_type < ( sizeof ( bustypes ) /
142 sizeof ( bustypes[0] ) ) );
143 bustype = bustypes[desc->bus_type];
144 assert ( bustype != NULL );
145 strncpy ( data, bustype, len );
146 return strlen ( bustype );
147 }
148
149 /**
150 * Fetch bus location setting
151 *
152 * @v netdev Network device
153 * @v data Buffer to fill with setting data
154 * @v len Length of buffer
155 * @ret len Length of setting data, or negative error
156 */
157 static int netdev_fetch_busloc ( struct net_device *netdev, void *data,
158 size_t len ) {
159 struct device_description *desc = &netdev->dev->desc;
160 uint32_t busloc;
161
162 busloc = cpu_to_be32 ( desc->location );
163 if ( len > sizeof ( busloc ) )
164 len = sizeof ( busloc );
165 memcpy ( data, &busloc, len );
166 return sizeof ( busloc );
167 }
168
169 /**
170 * Fetch bus ID setting
171 *
172 * @v netdev Network device
173 * @v data Buffer to fill with setting data
174 * @v len Length of buffer
175 * @ret len Length of setting data, or negative error
176 */
177 static int netdev_fetch_busid ( struct net_device *netdev, void *data,
178 size_t len ) {
179 struct device_description *desc = &netdev->dev->desc;
180 struct dhcp_netdev_desc dhcp_desc;
181
182 dhcp_desc.type = desc->bus_type;
183 dhcp_desc.vendor = htons ( desc->vendor );
184 dhcp_desc.device = htons ( desc->device );
185 if ( len > sizeof ( dhcp_desc ) )
186 len = sizeof ( dhcp_desc );
187 memcpy ( data, &dhcp_desc, len );
188 return sizeof ( dhcp_desc );
189 }
190
191 /**
192 * Fetch chip setting
193 *
194 * @v netdev Network device
195 * @v data Buffer to fill with setting data
196 * @v len Length of buffer
197 * @ret len Length of setting data, or negative error
198 */
199 static int netdev_fetch_chip ( struct net_device *netdev, void *data,
200 size_t len ) {
201 const char *chip = netdev->dev->driver_name;
202
203 strncpy ( data, chip, len );
204 return strlen ( chip );
205 }
206
207 /**
208 * Fetch ifname setting
209 *
210 * @v netdev Network device
211 * @v data Buffer to fill with setting data
212 * @v len Length of buffer
213 * @ret len Length of setting data, or negative error
214 */
215 static int netdev_fetch_ifname ( struct net_device *netdev, void *data,
216 size_t len ) {
217 const char *ifname = netdev->name;
218
219 strncpy ( data, ifname, len );
220 return strlen ( ifname );
221 }
222
223 /** A network device setting operation */
224 struct netdev_setting_operation {
225 /** Setting */
226 const struct setting *setting;
227 /** Store setting (or NULL if not supported)
228 *
229 * @v netdev Network device
230 * @v data Setting data, or NULL to clear setting
231 * @v len Length of setting data
232 * @ret rc Return status code
233 */
234 int ( * store ) ( struct net_device *netdev, const void *data,
235 size_t len );
236 /** Fetch setting
237 *
238 * @v netdev Network device
239 * @v data Buffer to fill with setting data
240 * @v len Length of buffer
241 * @ret len Length of setting data, or negative error
242 */
243 int ( * fetch ) ( struct net_device *netdev, void *data, size_t len );
244 };
245
246 /** Network device settings */
247 static struct netdev_setting_operation netdev_setting_operations[] = {
248 { &mac_setting, netdev_store_mac, netdev_fetch_mac },
249 { &bustype_setting, NULL, netdev_fetch_bustype },
250 { &busloc_setting, NULL, netdev_fetch_busloc },
251 { &busid_setting, NULL, netdev_fetch_busid },
252 { &chip_setting, NULL, netdev_fetch_chip },
253 { &ifname_setting, NULL, netdev_fetch_ifname },
254 };
255
256 /**
257 * Store value of network device setting
258 *
259 * @v settings Settings block
260 * @v setting Setting to store
261 * @v data Setting data, or NULL to clear setting
262 * @v len Length of setting data
263 * @ret rc Return status code
264 */
265 static int netdev_store ( struct settings *settings,
266 const struct setting *setting,
267 const void *data, size_t len ) {
268 struct net_device *netdev = container_of ( settings, struct net_device,
269 settings.settings );
270 struct netdev_setting_operation *op;
271 unsigned int i;
272
273 /* Handle network device-specific settings */
274 for ( i = 0 ; i < ( sizeof ( netdev_setting_operations ) /
275 sizeof ( netdev_setting_operations[0] ) ) ; i++ ) {
276 op = &netdev_setting_operations[i];
277 if ( setting_cmp ( setting, op->setting ) == 0 ) {
278 if ( op->store ) {
279 return op->store ( netdev, data, len );
280 } else {
281 return -ENOTSUP;
282 }
283 }
284 }
285
286 return generic_settings_store ( settings, setting, data, len );
287 }
288
289 /**
290 * Fetch value of network device setting
291 *
292 * @v settings Settings block
293 * @v setting Setting to fetch
294 * @v data Buffer to fill with setting data
295 * @v len Length of buffer
296 * @ret len Length of setting data, or negative error
297 */
298 static int netdev_fetch ( struct settings *settings, struct setting *setting,
299 void *data, size_t len ) {
300 struct net_device *netdev = container_of ( settings, struct net_device,
301 settings.settings );
302 struct netdev_setting_operation *op;
303 unsigned int i;
304
305 /* Handle network device-specific settings */
306 for ( i = 0 ; i < ( sizeof ( netdev_setting_operations ) /
307 sizeof ( netdev_setting_operations[0] ) ) ; i++ ) {
308 op = &netdev_setting_operations[i];
309 if ( setting_cmp ( setting, op->setting ) == 0 )
310 return op->fetch ( netdev, data, len );
311 }
312
313 return generic_settings_fetch ( settings, setting, data, len );
314 }
315
316 /**
317 * Clear network device settings
318 *
319 * @v settings Settings block
320 */
321 static void netdev_clear ( struct settings *settings ) {
322 generic_settings_clear ( settings );
323 }
324
325 /** Network device configuration settings operations */
326 struct settings_operations netdev_settings_operations = {
327 .store = netdev_store,
328 .fetch = netdev_fetch,
329 .clear = netdev_clear,
330 };
331
332 /**
333 * Redirect "netX" settings block
334 *
335 * @v settings Settings block
336 * @ret settings Underlying settings block
337 */
338 static struct settings * netdev_redirect ( struct settings *settings ) {
339 struct net_device *netdev;
340
341 /* Redirect to most recently opened network device */
342 netdev = last_opened_netdev();
343 if ( netdev ) {
344 return netdev_settings ( netdev );
345 } else {
346 return settings;
347 }
348 }
349
350 /** "netX" settings operations */
351 static struct settings_operations netdev_redirect_settings_operations = {
352 .redirect = netdev_redirect,
353 };
354
355 /** "netX" settings */
356 static struct settings netdev_redirect_settings = {
357 .refcnt = NULL,
358 .siblings = LIST_HEAD_INIT ( netdev_redirect_settings.siblings ),
359 .children = LIST_HEAD_INIT ( netdev_redirect_settings.children ),
360 .op = &netdev_redirect_settings_operations,
361 };
362
363 /** Initialise "netX" settings */
364 static void netdev_redirect_settings_init ( void ) {
365 int rc;
366
367 if ( ( rc = register_settings ( &netdev_redirect_settings, NULL,
368 "netX" ) ) != 0 ) {
369 DBG ( "Could not register netX settings: %s\n",
370 strerror ( rc ) );
371 return;
372 }
373 }
374
375 /** "netX" settings initialiser */
376 struct init_fn netdev_redirect_settings_init_fn __init_fn ( INIT_LATE ) = {
377 .initialise = netdev_redirect_settings_init,
378 };