These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / roms / ipxe / src / usr / ifmgmt.c
1 /*
2  * Copyright (C) 2007 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 <stdio.h>
28 #include <unistd.h>
29 #include <errno.h>
30 #include <ipxe/console.h>
31 #include <ipxe/netdevice.h>
32 #include <ipxe/device.h>
33 #include <ipxe/job.h>
34 #include <ipxe/monojob.h>
35 #include <ipxe/timer.h>
36 #include <usr/ifmgmt.h>
37
38 /** @file
39  *
40  * Network interface management
41  *
42  */
43
44 /** Default time to wait for link-up */
45 #define LINK_WAIT_TIMEOUT ( 15 * TICKS_PER_SEC )
46
47 /** Default unsuccessful configuration status code */
48 #define EADDRNOTAVAIL_CONFIG __einfo_error ( EINFO_EADDRNOTAVAIL_CONFIG )
49 #define EINFO_EADDRNOTAVAIL_CONFIG                                      \
50         __einfo_uniqify ( EINFO_EADDRNOTAVAIL, 0x01,                    \
51                           "No configuration methods succeeded" )
52
53 /**
54  * Open network device
55  *
56  * @v netdev            Network device
57  * @ret rc              Return status code
58  */
59 int ifopen ( struct net_device *netdev ) {
60         int rc;
61
62         if ( ( rc = netdev_open ( netdev ) ) != 0 ) {
63                 printf ( "Could not open %s: %s\n",
64                          netdev->name, strerror ( rc ) );
65                 return rc;
66         }
67
68         return 0;
69 }
70
71 /**
72  * Close network device
73  *
74  * @v netdev            Network device
75  */
76 void ifclose ( struct net_device *netdev ) {
77         netdev_close ( netdev );
78 }
79
80 /**
81  * Print network device error breakdown
82  *
83  * @v stats             Network device statistics
84  * @v prefix            Message prefix
85  */
86 static void ifstat_errors ( struct net_device_stats *stats,
87                             const char *prefix ) {
88         unsigned int i;
89
90         for ( i = 0 ; i < ( sizeof ( stats->errors ) /
91                             sizeof ( stats->errors[0] ) ) ; i++ ) {
92                 if ( stats->errors[i].count )
93                         printf ( "  [%s: %d x \"%s\"]\n", prefix,
94                                  stats->errors[i].count,
95                                  strerror ( stats->errors[i].rc ) );
96         }
97 }
98
99 /**
100  * Print status of network device
101  *
102  * @v netdev            Network device
103  */
104 void ifstat ( struct net_device *netdev ) {
105         printf ( "%s: %s using %s on %s (%s)\n"
106                  "  [Link:%s%s, TX:%d TXE:%d RX:%d RXE:%d]\n",
107                  netdev->name, netdev_addr ( netdev ),
108                  netdev->dev->driver_name, netdev->dev->name,
109                  ( netdev_is_open ( netdev ) ? "open" : "closed" ),
110                  ( netdev_link_ok ( netdev ) ? "up" : "down" ),
111                  ( netdev_link_blocked ( netdev ) ? " (blocked)" : "" ),
112                  netdev->tx_stats.good, netdev->tx_stats.bad,
113                  netdev->rx_stats.good, netdev->rx_stats.bad );
114         if ( ! netdev_link_ok ( netdev ) ) {
115                 printf ( "  [Link status: %s]\n",
116                          strerror ( netdev->link_rc ) );
117         }
118         ifstat_errors ( &netdev->tx_stats, "TXE" );
119         ifstat_errors ( &netdev->rx_stats, "RXE" );
120 }
121
122 /** Network device poller */
123 struct ifpoller {
124         /** Job control interface */
125         struct interface job;
126         /** Network device */
127         struct net_device *netdev;
128         /** Network device configurator (if applicable) */
129         struct net_device_configurator *configurator;
130         /**
131          * Check progress
132          *
133          * @v ifpoller          Network device poller
134          * @ret ongoing_rc      Ongoing job status code (if known)
135          */
136         int ( * progress ) ( struct ifpoller *ifpoller );
137 };
138
139 /**
140  * Report network device poller progress
141  *
142  * @v ifpoller          Network device poller
143  * @v progress          Progress report to fill in
144  * @ret ongoing_rc      Ongoing job status code (if known)
145  */
146 static int ifpoller_progress ( struct ifpoller *ifpoller,
147                                struct job_progress *progress __unused ) {
148
149         /* Hand off to current progress checker */
150         return ifpoller->progress ( ifpoller );
151 }
152
153 /** Network device poller operations */
154 static struct interface_operation ifpoller_job_op[] = {
155         INTF_OP ( job_progress, struct ifpoller *, ifpoller_progress ),
156 };
157
158 /** Network device poller descriptor */
159 static struct interface_descriptor ifpoller_job_desc =
160         INTF_DESC ( struct ifpoller, job, ifpoller_job_op );
161
162 /**
163  * Poll network device until completion
164  *
165  * @v netdev            Network device
166  * @v configurator      Network device configurator (if applicable)
167  * @v timeout           Timeout period, in ticks
168  * @v progress          Method to check progress
169  * @ret rc              Return status code
170  */
171 static int ifpoller_wait ( struct net_device *netdev,
172                            struct net_device_configurator *configurator,
173                            unsigned long timeout,
174                            int ( * progress ) ( struct ifpoller *ifpoller ) ) {
175         static struct ifpoller ifpoller = {
176                 .job = INTF_INIT ( ifpoller_job_desc ),
177         };
178
179         ifpoller.netdev = netdev;
180         ifpoller.configurator = configurator;
181         ifpoller.progress = progress;
182         intf_plug_plug ( &monojob, &ifpoller.job );
183         return monojob_wait ( "", timeout );
184 }
185
186 /**
187  * Check link-up progress
188  *
189  * @v ifpoller          Network device poller
190  * @ret ongoing_rc      Ongoing job status code (if known)
191  */
192 static int iflinkwait_progress ( struct ifpoller *ifpoller ) {
193         struct net_device *netdev = ifpoller->netdev;
194         int ongoing_rc = netdev->link_rc;
195
196         /* Terminate successfully if link is up */
197         if ( ongoing_rc == 0 )
198                 intf_close ( &ifpoller->job, 0 );
199
200         /* Otherwise, report link status as ongoing job status */
201         return ongoing_rc;
202 }
203
204 /**
205  * Wait for link-up, with status indication
206  *
207  * @v netdev            Network device
208  * @v timeout           Timeout period, in ticks
209  */
210 int iflinkwait ( struct net_device *netdev, unsigned long timeout ) {
211         int rc;
212
213         /* Ensure device is open */
214         if ( ( rc = ifopen ( netdev ) ) != 0 )
215                 return rc;
216
217         /* Return immediately if link is already up */
218         netdev_poll ( netdev );
219         if ( netdev_link_ok ( netdev ) )
220                 return 0;
221
222         /* Wait for link-up */
223         printf ( "Waiting for link-up on %s", netdev->name );
224         return ifpoller_wait ( netdev, NULL, timeout, iflinkwait_progress );
225 }
226
227 /**
228  * Check configuration progress
229  *
230  * @v ifpoller          Network device poller
231  * @ret ongoing_rc      Ongoing job status code (if known)
232  */
233 static int ifconf_progress ( struct ifpoller *ifpoller ) {
234         struct net_device *netdev = ifpoller->netdev;
235         struct net_device_configurator *configurator = ifpoller->configurator;
236         struct net_device_configuration *config;
237         int rc;
238
239         /* Do nothing unless configuration has completed */
240         if ( netdev_configuration_in_progress ( netdev ) )
241                 return 0;
242
243         /* Terminate with appropriate overall return status code */
244         if ( configurator ) {
245                 config = netdev_configuration ( netdev, configurator );
246                 rc = config->rc;
247         } else {
248                 rc = ( netdev_configuration_ok ( netdev ) ?
249                        0 : -EADDRNOTAVAIL_CONFIG );
250         }
251         intf_close ( &ifpoller->job, rc );
252
253         return rc;
254 }
255
256 /**
257  * Perform network device configuration
258  *
259  * @v netdev            Network device
260  * @v configurator      Network device configurator, or NULL to use all
261  * @ret rc              Return status code
262  */
263 int ifconf ( struct net_device *netdev,
264              struct net_device_configurator *configurator ) {
265         int rc;
266
267         /* Ensure device is open and link is up */
268         if ( ( rc = iflinkwait ( netdev, LINK_WAIT_TIMEOUT ) ) != 0 )
269                 return rc;
270
271         /* Start configuration */
272         if ( configurator ) {
273                 if ( ( rc = netdev_configure ( netdev, configurator ) ) != 0 ) {
274                         printf ( "Could not configure %s via %s: %s\n",
275                                  netdev->name, configurator->name,
276                                  strerror ( rc ) );
277                         return rc;
278                 }
279         } else {
280                 if ( ( rc = netdev_configure_all ( netdev ) ) != 0 ) {
281                         printf ( "Could not configure %s: %s\n",
282                                  netdev->name, strerror ( rc ) );
283                         return rc;
284                 }
285         }
286
287         /* Wait for configuration to complete */
288         printf ( "Configuring %s%s%s(%s %s)",
289                  ( configurator ? "[" : "" ),
290                  ( configurator ? configurator->name : "" ),
291                  ( configurator ? "] " : "" ),
292                  netdev->name, netdev->ll_protocol->ntoa ( netdev->ll_addr ) );
293         return ifpoller_wait ( netdev, configurator, 0, ifconf_progress );
294 }