]>
git.ipfire.org Git - people/teissler/ipfire-2.x.git/blob - src/hwinfo/src/hd/net.c
10 #include <sys/ioctl.h>
11 #include <sys/socket.h>
18 #include <linux/sockios.h>
19 #include <linux/ethtool.h>
20 #include <linux/if_arp.h>
26 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
27 * gather network interface info
29 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
32 static void get_driverinfo(hd_data_t
*hd_data
, hd_t
*hd
);
33 static void get_linkstate(hd_data_t
*hd_data
, hd_t
*hd
);
34 static void add_xpnet(hd_data_t
*hdata
);
35 static void add_iseries(hd_data_t
*hdata
);
36 static void add_uml(hd_data_t
*hdata
);
39 * This is independent of the other scans.
42 void hd_scan_net(hd_data_t
*hd_data
)
51 struct sysfs_class
*sf_class
;
52 struct sysfs_class_device
*sf_cdev
;
53 struct sysfs_device
*sf_dev
;
54 struct sysfs_driver
*sf_drv
;
55 struct dlist
*sf_cdev_list
;
57 if(!hd_probe_feature(hd_data
, pr_net
)) return;
59 hd_data
->module
= mod_net
;
62 remove_hd_entries(hd_data
);
63 hd_data
->net
= free_str_list(hd_data
->net
);
65 PROGRESS(1, 0, "get network data");
67 sf_class
= sysfs_open_class("net");
70 ADD2LOG("sysfs: no such class: net\n");
74 sf_cdev_list
= sysfs_get_class_devices(sf_class
);
75 if(sf_cdev_list
) dlist_for_each_data(sf_cdev_list
, sf_cdev
, struct sysfs_class_device
) {
79 " net interface: name = %s, classname = %s, path = %s\n",
82 hd_sysfs_id(sf_cdev
->path
)
86 if(hd_attr_uint(sysfs_get_classdev_attr(sf_cdev
, "type"), &ul0
, 0)) {
88 ADD2LOG(" type = %d\n", if_type
);
92 if((s
= hd_attr_str(sysfs_get_classdev_attr(sf_cdev
, "address")))) {
93 hw_addr
= canon_str(s
, strlen(s
));
94 ADD2LOG(" hw_addr = %s\n", hw_addr
);
97 sf_dev
= sysfs_get_classdev_device(sf_cdev
);
99 ADD2LOG(" net device: path = %s\n", hd_sysfs_id(sf_dev
->path
));
102 sf_drv
= sysfs_get_classdev_driver(sf_cdev
);
105 " net driver: name = %s, path = %s\n",
107 hd_sysfs_id(sf_drv
->path
)
111 hd
= add_hd_entry(hd_data
, __LINE__
, 0);
112 hd
->base_class
.id
= bc_network_interface
;
113 hd
->sub_class
.id
= sc_nif_other
;
116 if(hw_addr
&& strspn(hw_addr
, "0:") != strlen(hw_addr
)) {
117 res1
= new_mem(sizeof *res1
);
118 res1
->hwaddr
.type
= res_hwaddr
;
119 res1
->hwaddr
.addr
= new_str(hw_addr
);
120 add_res_entry(&hd
->res
, res1
);
123 hw_addr
= free_mem(hw_addr
);
125 hd
->unix_dev_name
= new_str(sf_cdev
->name
);
126 hd
->sysfs_id
= new_str(hd_sysfs_id(sf_cdev
->path
));
129 add_str_list(&hd
->drivers
, sf_drv
->name
);
132 get_driverinfo(hd_data
, hd
);
136 hd
->sysfs_device_link
= new_str(hd_sysfs_id(sf_dev
->path
));
138 hd_card
= hd_find_sysfs_id(hd_data
, hd_sysfs_id(sf_dev
->path
));
140 hd
->attached_to
= hd_card
->idx
;
142 /* for cards with strange pci classes */
143 hd_set_hw_class(hd_card
, hw_network_ctrl
);
145 /* add hw addr to network card */
148 for(res
= hd_card
->res
; res
; res
= res
->next
) {
150 res
->any
.type
== res_hwaddr
&&
151 !strcmp(res
->hwaddr
.addr
, res1
->hwaddr
.addr
)
158 res
= new_mem(sizeof *res
);
159 res
->hwaddr
.type
= res_hwaddr
;
160 res
->hwaddr
.addr
= new_str(res1
->hwaddr
.addr
);
161 add_res_entry(&hd_card
->res
, res
);
164 /* add interface names */
165 if(hd
->unix_dev_name
) {
166 if(!search_str_list(hd_card
->unix_dev_names
, hd
->unix_dev_name
)) {
167 add_str_list(&hd_card
->unix_dev_names
, hd
->unix_dev_name
);
169 if(!hd_card
->unix_dev_name
) {
170 hd_card
->unix_dev_name
= new_str(hd
->unix_dev_name
);
182 "myri" sc_nif_myrinet
188 case ARPHRD_ETHER
: /* eth */
189 hd
->sub_class
.id
= sc_nif_ethernet
;
191 case ARPHRD_LOOPBACK
: /* lo */
192 hd
->sub_class
.id
= sc_nif_loopback
;
194 case ARPHRD_SIT
: /* sit */
195 hd
->sub_class
.id
= sc_nif_sit
;
197 case ARPHRD_FDDI
: /* fddi */
198 hd
->sub_class
.id
= sc_nif_fddi
;
200 case ARPHRD_IEEE802_TR
: /* tr */
201 hd
->sub_class
.id
= sc_nif_tokenring
;
204 case ARPHRD_IEEE802
: /* fc */
205 hd
->sub_class
.id
= sc_nif_fc
;
210 if(!strcmp(hd
->unix_dev_name
, "lo")) {
211 hd
->sub_class
.id
= sc_nif_loopback
;
213 else if(sscanf(hd
->unix_dev_name
, "eth%u", &u
) == 1) {
214 hd
->sub_class
.id
= sc_nif_ethernet
;
217 else if(sscanf(hd
->unix_dev_name
, "tr%u", &u
) == 1) {
218 hd
->sub_class
.id
= sc_nif_tokenring
;
221 else if(sscanf(hd
->unix_dev_name
, "fddi%u", &u
) == 1) {
222 hd
->sub_class
.id
= sc_nif_fddi
;
225 else if(sscanf(hd
->unix_dev_name
, "ctc%u", &u
) == 1) {
226 hd
->sub_class
.id
= sc_nif_ctc
;
229 else if(sscanf(hd
->unix_dev_name
, "iucv%u", &u
) == 1) {
230 hd
->sub_class
.id
= sc_nif_iucv
;
233 else if(sscanf(hd
->unix_dev_name
, "hsi%u", &u
) == 1) {
234 hd
->sub_class
.id
= sc_nif_hsi
;
237 else if(sscanf(hd
->unix_dev_name
, "qeth%u", &u
) == 1) {
238 hd
->sub_class
.id
= sc_nif_qeth
;
241 else if(sscanf(hd
->unix_dev_name
, "escon%u", &u
) == 1) {
242 hd
->sub_class
.id
= sc_nif_escon
;
245 else if(sscanf(hd
->unix_dev_name
, "myri%u", &u
) == 1) {
246 hd
->sub_class
.id
= sc_nif_myrinet
;
249 else if(sscanf(hd
->unix_dev_name
, "sit%u", &u
) == 1) {
250 hd
->sub_class
.id
= sc_nif_sit
; /* ipv6 over ipv4 tunnel */
253 else if(sscanf(hd
->unix_dev_name
, "wlan%u", &u
) == 1) {
254 hd
->sub_class
.id
= sc_nif_wlan
;
257 else if(sscanf(hd
->unix_dev_name
, "xp%u", &u
) == 1) {
258 hd
->sub_class
.id
= sc_nif_xp
;
261 else if(sscanf(hd
->unix_dev_name
, "usb%u", &u
) == 1) {
262 hd
->sub_class
.id
= sc_nif_usb
;
265 /* ##### add more interface names here */
267 hd
->bus
.id
= bus_none
;
272 (hd_card
->base_class
.id
== 0 && hd_card
->sub_class
.id
== 0) ||
273 (hd_card
->base_class
.id
== bc_network
&& hd_card
->sub_class
.id
== 0x80)
275 switch(hd
->sub_class
.id
) {
276 case sc_nif_ethernet
:
277 hd_card
->base_class
.id
= bc_network
;
278 hd_card
->sub_class
.id
= 0;
282 hd_card
->base_class
.id
= bc_network
;
283 hd_card
->sub_class
.id
= 0x91;
290 sysfs_close_class(sf_class
);
292 if(hd_is_sgi_altix(hd_data
)) add_xpnet(hd_data
);
293 if(hd_is_iseries(hd_data
)) add_iseries(hd_data
);
296 /* add link status info */
297 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
299 hd
->module
== hd_data
->module
&&
300 hd
->base_class
.id
== bc_network_interface
302 get_linkstate(hd_data
, hd
);
304 if(!(hd_card
= hd_get_device_by_idx(hd_data
, hd
->attached_to
))) continue;
306 for(res
= hd
->res
; res
; res
= res
->next
) {
307 if(res
->any
.type
== res_link
) break;
311 for(res1
= hd_card
->res
; res1
; res1
= res1
->next
) {
312 if(res1
->any
.type
== res_link
) break;
315 res1
= new_mem(sizeof *res1
);
316 res1
->link
.type
= res_link
;
317 res1
->link
.state
= res
->link
.state
;
318 add_res_entry(&hd_card
->res
, res1
);
327 * Get it the classical way, for drivers that don't support sysfs (veth).
329 void get_driverinfo(hd_data_t
*hd_data
, hd_t
*hd
)
332 struct ethtool_drvinfo drvinfo
= { cmd
:ETHTOOL_GDRVINFO
};
335 if(!hd
->unix_dev_name
) return;
337 if(strlen(hd
->unix_dev_name
) > sizeof ifr
.ifr_name
- 1) return;
339 if((fd
= socket(PF_INET
, SOCK_DGRAM
, 0)) == -1) return;
341 /* get driver info */
342 memset(&ifr
, 0, sizeof ifr
);
343 strcpy(ifr
.ifr_name
, hd
->unix_dev_name
);
344 ifr
.ifr_data
= (caddr_t
) &drvinfo
;
345 if(ioctl(fd
, SIOCETHTOOL
, &ifr
) == 0) {
346 ADD2LOG(" ethtool driver: %s\n", drvinfo
.driver
);
347 ADD2LOG(" ethtool bus: %s\n", drvinfo
.bus_info
);
349 add_str_list(&hd
->drivers
, drvinfo
.driver
);
352 ADD2LOG(" GDRVINFO ethtool error: %s\n", strerror(errno
));
360 * Check network link status.
362 void get_linkstate(hd_data_t
*hd_data
, hd_t
*hd
)
365 struct ethtool_value linkstatus
= { cmd
:ETHTOOL_GLINK
};
369 if(!hd
->unix_dev_name
) return;
371 if(strlen(hd
->unix_dev_name
) > sizeof ifr
.ifr_name
- 1) return;
373 if((fd
= socket(PF_INET
, SOCK_DGRAM
, 0)) == -1) return;
375 /* get driver info */
376 memset(&ifr
, 0, sizeof ifr
);
377 strcpy(ifr
.ifr_name
, hd
->unix_dev_name
);
378 ifr
.ifr_data
= (caddr_t
) &linkstatus
;
379 if(ioctl(fd
, SIOCETHTOOL
, &ifr
) == 0) {
380 ADD2LOG(" %s: ethtool link state: %d\n", hd
->unix_dev_name
, linkstatus
.data
);
381 res
= new_mem(sizeof *res
);
382 res
->link
.type
= res_link
;
383 res
->link
.state
= linkstatus
.data
? 1 : 0;
384 add_res_entry(&hd
->res
, res
);
387 ADD2LOG(" %s: GLINK ethtool error: %s\n", hd
->unix_dev_name
, strerror(errno
));
395 * SGI Altix cross partition network.
397 void add_xpnet(hd_data_t
*hd_data
)
400 hd_res_t
*res
, *res2
;
402 hd_card
= add_hd_entry(hd_data
, __LINE__
, 0);
403 hd_card
->base_class
.id
= bc_network
;
404 hd_card
->sub_class
.id
= 0x83;
406 hd_card
->vendor
.id
= MAKE_ID(TAG_SPECIAL
, 0x4002);
407 hd_card
->device
.id
= MAKE_ID(TAG_SPECIAL
, 1);
409 if(hd_module_is_active(hd_data
, "xpnet")) {
410 add_str_list(&hd_card
->drivers
, "xpnet");
413 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
415 hd
->module
== hd_data
->module
&&
416 hd
->base_class
.id
== bc_network_interface
&&
417 hd
->sub_class
.id
== sc_nif_xp
419 hd
->attached_to
= hd_card
->idx
;
421 for(res
= hd
->res
; res
; res
= res
->next
) {
422 if(res
->any
.type
== res_hwaddr
) break;
426 res2
= new_mem(sizeof *res2
);
427 res2
->hwaddr
.type
= res_hwaddr
;
428 res2
->hwaddr
.addr
= new_str(res
->hwaddr
.addr
);
429 add_res_entry(&hd_card
->res
, res2
);
439 * iSeries veth devices.
441 void add_iseries(hd_data_t
*hd_data
)
444 hd_res_t
*res
, *res2
;
445 unsigned i
, cardmask
= 0, card_cnt
= 0;
446 str_list_t
*sl0
, *sl
;
448 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
450 hd
->module
== hd_data
->module
&&
451 hd
->base_class
.id
== bc_network_interface
&&
452 search_str_list(hd
->drivers
, "veth")
454 hd_card
= add_hd_entry(hd_data
, __LINE__
, 0);
455 hd_card
->base_class
.id
= bc_network
;
456 hd_card
->sub_class
.id
= 0x00;
457 hd_card
->vendor
.id
= MAKE_ID(TAG_SPECIAL
, 0x6001); // IBM
458 hd_card
->device
.id
= MAKE_ID(TAG_SPECIAL
, 0x1000);
459 add_str_list(&hd_card
->drivers
, "iseries_veth");
460 hd_card
->slot
= card_cnt
++;
461 str_printf(&hd_card
->device
.name
, 0, "Virtual Ethernet card");
462 hd
->attached_to
= hd_card
->idx
;
464 for(res
= hd
->res
; res
; res
= res
->next
) {
465 if(res
->any
.type
== res_hwaddr
) break;
471 res2
= new_mem(sizeof *res2
);
472 res2
->hwaddr
.type
= res_hwaddr
;
473 res2
->hwaddr
.addr
= new_str(res
->hwaddr
.addr
);
474 add_res_entry(&hd_card
->res
, res2
);
475 if (sscanf(res
->hwaddr
.addr
, "02:01:ff:%x:ff:", &slotno
)) {
476 hd_card
->slot
= slotno
;
477 str_printf(&hd_card
->device
.name
, 0, "Virtual Ethernet card %d", hd_card
->slot
);
484 sl0
= read_file("/proc/iSeries/config", 0, 0);
485 for(sl
= sl0
; sl
; sl
= sl
->next
) {
486 if(sscanf(sl
->str
, "AVAILABLE_VETH=%x", &cardmask
) == 1)
491 for (i
= 0; i
< 16; i
++) {
492 if ((0x8000 >> i
) & cardmask
) {
493 hd_card
= add_hd_entry(hd_data
, __LINE__
, 0);
494 hd_card
->base_class
.id
= bc_network
;
495 hd_card
->sub_class
.id
= 0x00;
496 hd_card
->vendor
.id
= MAKE_ID(TAG_SPECIAL
, 0x6001); // IBM
497 hd_card
->device
.id
= MAKE_ID(TAG_SPECIAL
, 0x1000);
499 str_printf(&hd_card
->device
.name
, 0, "Virtual Ethernet card %d", i
);
509 void add_uml(hd_data_t
*hd_data
)
512 hd_res_t
*res
, *res2
;
513 unsigned card_cnt
= 0;
515 for(hd
= hd_data
->hd
; hd
; hd
= hd
->next
) {
517 hd
->module
== hd_data
->module
&&
518 hd
->base_class
.id
== bc_network_interface
&&
519 search_str_list(hd
->drivers
, "uml virtual ethernet")
521 hd_card
= add_hd_entry(hd_data
, __LINE__
, 0);
522 hd_card
->base_class
.id
= bc_network
;
523 hd_card
->sub_class
.id
= 0x00;
524 hd_card
->vendor
.id
= MAKE_ID(TAG_SPECIAL
, 0x6010); // UML
525 hd_card
->device
.id
= MAKE_ID(TAG_SPECIAL
, 0x0001);
526 hd_card
->slot
= card_cnt
++;
527 str_printf(&hd_card
->device
.name
, 0, "Virtual Ethernet card %d", hd_card
->slot
);
528 // add_str_list(&hd_card->drivers, "veth");
530 hd
->attached_to
= hd_card
->idx
;
532 for(res
= hd
->res
; res
; res
= res
->next
) {
533 if(res
->any
.type
== res_hwaddr
) break;
537 res2
= new_mem(sizeof *res2
);
538 res2
->hwaddr
.type
= res_hwaddr
;
539 res2
->hwaddr
.addr
= new_str(res
->hwaddr
.addr
);
540 add_res_entry(&hd_card
->res
, res2
);