Line data Source code
1 : #include "fd_linux_bond.h"
2 :
3 : #include <errno.h>
4 : #include <stdio.h>
5 : #include <sys/stat.h>
6 :
7 : int
8 3 : fd_bonding_is_master( char const * device ) {
9 3 : char path[ PATH_MAX ];
10 3 : FD_TEST( fd_cstr_printf_check( path, PATH_MAX, NULL, "/sys/class/net/%s/bonding", device ) );
11 3 : struct stat st;
12 3 : int err = stat( path, &st );
13 3 : if( FD_UNLIKELY( err && errno != ENOENT ) )
14 0 : FD_LOG_ERR(( "error checking if device `%s` is bonded, stat(%s) failed (%i-%s)",
15 3 : device, path, errno, fd_io_strerror( errno ) ));
16 3 : return !err;
17 3 : }
18 :
19 : static void
20 : read_slaves( char const * device,
21 6 : char output[ 4096 ] ) {
22 6 : char path[ PATH_MAX ];
23 6 : FD_TEST( fd_cstr_printf_check( path, PATH_MAX, NULL, "/sys/class/net/%s/bonding/slaves", device ) );
24 :
25 6 : FILE * fp = fopen( path, "r" );
26 6 : if( FD_UNLIKELY( !fp ) )
27 0 : FD_LOG_ERR(( "error configuring network device, fopen(%s) failed (%i-%s)", path, errno, fd_io_strerror( errno ) ));
28 6 : if( FD_UNLIKELY( !fgets( output, 4096, fp ) ) )
29 0 : FD_LOG_ERR(( "error configuring network device, fgets(%s) failed (%i-%s)", path, errno, fd_io_strerror( errno ) ));
30 6 : if( FD_UNLIKELY( feof( fp ) ) ) FD_LOG_ERR(( "error configuring network device, fgets(%s) failed (EOF)", path ));
31 6 : if( FD_UNLIKELY( ferror( fp ) ) ) FD_LOG_ERR(( "error configuring network device, fgets(%s) failed (error)", path ));
32 6 : if( FD_UNLIKELY( strlen( output ) == 4095 ) ) FD_LOG_ERR(( "line too long in `%s`", path ));
33 6 : if( FD_UNLIKELY( strlen( output ) == 0 ) ) FD_LOG_ERR(( "line empty in `%s`", path ));
34 6 : if( FD_UNLIKELY( fclose( fp ) ) )
35 0 : FD_LOG_ERR(( "error configuring network device, fclose(%s) failed (%i-%s)", path, errno, fd_io_strerror( errno ) ));
36 6 : output[ strlen( output ) - 1 ] = '\0';
37 6 : }
38 :
39 : fd_bonding_slave_iter_t *
40 : fd_bonding_slave_iter_init(
41 : fd_bonding_slave_iter_t * iter,
42 : char const * device
43 6 : ) {
44 6 : read_slaves( device, iter->line );
45 6 : iter->saveptr = NULL;
46 6 : iter->tok = strtok_r( iter->line, " \t", &iter->saveptr );
47 6 : return iter;
48 6 : }
49 :
50 : int
51 18 : fd_bonding_slave_iter_done( fd_bonding_slave_iter_t const * iter ) {
52 18 : return !iter->tok;
53 18 : }
54 :
55 : void
56 : fd_bonding_slave_iter_next(
57 : fd_bonding_slave_iter_t * iter
58 12 : ) {
59 12 : iter->tok = strtok_r( NULL, " \t", &iter->saveptr );
60 12 : }
61 :
62 : char const *
63 : fd_bonding_slave_iter_ele(
64 : fd_bonding_slave_iter_t const * iter
65 6 : ) {
66 6 : return iter->tok;
67 6 : }
68 :
69 : int
70 3 : fd_bonding_is_lacp( char const * device ) {
71 3 : char path[ PATH_MAX ];
72 3 : FD_TEST( fd_cstr_printf_check( path, PATH_MAX, NULL, "/sys/class/net/%s/bonding/mode", device ) );
73 :
74 3 : FILE * fp = fopen( path, "r" );
75 3 : if( FD_UNLIKELY( !fp ) ) {
76 0 : FD_LOG_WARNING(( "failed to detect bonding mode of device `%s`, fopen(%s) failed (%i-%s)",
77 0 : device, path, errno, fd_io_strerror( errno ) ));
78 0 : return 0;
79 0 : }
80 :
81 : /* The mode node holds the mode name followed by its numeric ID,
82 : e.g. "802.3ad 4" */
83 3 : char line[ 64 ];
84 3 : errno = 0;
85 3 : char * res = fgets( line, sizeof(line), fp );
86 3 : int err = errno;
87 3 : fclose( fp );
88 3 : if( FD_UNLIKELY( !res ) ) {
89 0 : FD_LOG_WARNING(( "failed to detect bonding mode of device `%s`, fgets(%s) failed (%i-%s)",
90 0 : device, path, err, fd_io_strerror( err ) ));
91 0 : return 0;
92 0 : }
93 :
94 3 : return 0==strncmp( line, "802.3ad ", 8UL );
95 3 : }
96 :
97 : uint
98 3 : fd_bonding_slave_cnt( char const * device ) {
99 3 : fd_bonding_slave_iter_t iter_[1];
100 3 : uint cnt = 0U;
101 3 : for( fd_bonding_slave_iter_t * iter = fd_bonding_slave_iter_init( iter_, device );
102 9 : !fd_bonding_slave_iter_done( iter );
103 6 : fd_bonding_slave_iter_next( iter ) ) {
104 6 : cnt++;
105 6 : }
106 3 : return cnt;
107 3 : }
|