iPXE
netvsc.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 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 (at your option) 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 /** @file
27  *
28  * Hyper-V network virtual service client
29  *
30  * The network virtual service client (NetVSC) connects to the network
31  * virtual service provider (NetVSP) via the Hyper-V virtual machine
32  * bus (VMBus). It provides a transport layer for RNDIS packets.
33  */
34 
35 #include <string.h>
36 #include <errno.h>
37 #include <unistd.h>
38 #include <byteswap.h>
39 #include <ipxe/umalloc.h>
40 #include <ipxe/rndis.h>
41 #include <ipxe/vmbus.h>
42 #include "netvsc.h"
43 
44 /**
45  * Send control message and wait for completion
46  *
47  * @v netvsc NetVSC device
48  * @v xrid Relative transaction ID
49  * @v data Data
50  * @v len Length of data
51  * @ret rc Return status code
52  */
53 static int netvsc_control ( struct netvsc_device *netvsc, unsigned int xrid,
54  const void *data, size_t len ) {
55  uint64_t xid = ( NETVSC_BASE_XID + xrid );
56  unsigned int i;
57  int rc;
58 
59  /* Send control message */
60  if ( ( rc = vmbus_send_control ( netvsc->vmdev, xid, data, len ) ) !=0){
61  DBGC ( netvsc, "NETVSC %s could not send control message: %s\n",
62  netvsc->name, strerror ( rc ) );
63  return rc;
64  }
65 
66  /* Record transaction ID */
67  netvsc->wait_xrid = xrid;
68 
69  /* Wait for operation to complete */
70  for ( i = 0 ; i < NETVSC_MAX_WAIT_MS ; i++ ) {
71 
72  /* Check for completion */
73  if ( ! netvsc->wait_xrid )
74  return netvsc->wait_rc;
75 
76  /* Poll VMBus device */
77  vmbus_poll ( netvsc->vmdev );
78 
79  /* Delay for 1ms */
80  mdelay ( 1 );
81  }
82 
83  DBGC ( netvsc, "NETVSC %s timed out waiting for XRID %d\n",
84  netvsc->name, xrid );
85  vmbus_dump_channel ( netvsc->vmdev );
86  return -ETIMEDOUT;
87 }
88 
89 /**
90  * Handle generic completion
91  *
92  * @v netvsc NetVSC device
93  * @v data Data
94  * @v len Length of data
95  * @ret rc Return status code
96  */
97 static int netvsc_completed ( struct netvsc_device *netvsc __unused,
98  const void *data __unused, size_t len __unused ) {
99  return 0;
100 }
101 
102 /**
103  * Initialise communication
104  *
105  * @v netvsc NetVSC device
106  * @ret rc Return status code
107  */
108 static int netvsc_initialise ( struct netvsc_device *netvsc ) {
109  struct netvsc_init_message msg;
110  int rc;
111 
112  /* Construct message */
113  memset ( &msg, 0, sizeof ( msg ) );
114  msg.header.type = cpu_to_le32 ( NETVSC_INIT_MSG );
115  msg.min = cpu_to_le32 ( NETVSC_VERSION_1 );
116  msg.max = cpu_to_le32 ( NETVSC_VERSION_1 );
117 
118  /* Send message and wait for completion */
119  if ( ( rc = netvsc_control ( netvsc, NETVSC_INIT_XRID, &msg,
120  sizeof ( msg ) ) ) != 0 ) {
121  DBGC ( netvsc, "NETVSC %s could not initialise: %s\n",
122  netvsc->name, strerror ( rc ) );
123  return rc;
124  }
125 
126  return 0;
127 }
128 
129 /**
130  * Handle initialisation completion
131  *
132  * @v netvsc NetVSC device
133  * @v data Data
134  * @v len Length of data
135  * @ret rc Return status code
136  */
137 static int
138 netvsc_initialised ( struct netvsc_device *netvsc, const void *data,
139  size_t len ) {
140  const struct netvsc_init_completion *cmplt = data;
141 
142  /* Check completion */
143  if ( len < sizeof ( *cmplt ) ) {
144  DBGC ( netvsc, "NETVSC %s underlength initialisation "
145  "completion (%zd bytes)\n", netvsc->name, len );
146  return -EINVAL;
147  }
148  if ( cmplt->header.type != cpu_to_le32 ( NETVSC_INIT_CMPLT ) ) {
149  DBGC ( netvsc, "NETVSC %s unexpected initialisation completion "
150  "type %d\n", netvsc->name,
151  le32_to_cpu ( cmplt->header.type ) );
152  return -EPROTO;
153  }
154  if ( cmplt->status != cpu_to_le32 ( NETVSC_OK ) ) {
155  DBGC ( netvsc, "NETVSC %s initialisation failure status %d\n",
156  netvsc->name, le32_to_cpu ( cmplt->status ) );
157  return -EPROTO;
158  }
159 
160  return 0;
161 }
162 
163 /**
164  * Set NDIS version
165  *
166  * @v netvsc NetVSC device
167  * @ret rc Return status code
168  */
169 static int netvsc_ndis_version ( struct netvsc_device *netvsc ) {
171  int rc;
172 
173  /* Construct message */
174  memset ( &msg, 0, sizeof ( msg ) );
175  msg.header.type = cpu_to_le32 ( NETVSC_NDIS_VERSION_MSG );
176  msg.major = cpu_to_le32 ( NETVSC_NDIS_MAJOR );
177  msg.minor = cpu_to_le32 ( NETVSC_NDIS_MINOR );
178 
179  /* Send message and wait for completion */
180  if ( ( rc = netvsc_control ( netvsc, NETVSC_NDIS_VERSION_XRID,
181  &msg, sizeof ( msg ) ) ) != 0 ) {
182  DBGC ( netvsc, "NETVSC %s could not set NDIS version: %s\n",
183  netvsc->name, strerror ( rc ) );
184  return rc;
185  }
186 
187  return 0;
188 }
189 
190 /**
191  * Establish data buffer
192  *
193  * @v netvsc NetVSC device
194  * @v buffer Data buffer
195  * @ret rc Return status code
196  */
197 static int netvsc_establish_buffer ( struct netvsc_device *netvsc,
198  struct netvsc_buffer *buffer ) {
200  int rc;
201 
202  /* Construct message */
203  memset ( &msg, 0, sizeof ( msg ) );
204  msg.header.type = cpu_to_le32 ( buffer->establish_type );
205  msg.gpadl = cpu_to_le32 ( buffer->gpadl );
206  msg.pageset = buffer->pages.pageset; /* Already protocol-endian */
207 
208  /* Send message and wait for completion */
209  if ( ( rc = netvsc_control ( netvsc, buffer->establish_xrid, &msg,
210  sizeof ( msg ) ) ) != 0 ) {
211  DBGC ( netvsc, "NETVSC %s could not establish buffer: %s\n",
212  netvsc->name, strerror ( rc ) );
213  return rc;
214  }
215 
216  return 0;
217 }
218 
219 /**
220  * Handle establish receive data buffer completion
221  *
222  * @v netvsc NetVSC device
223  * @v data Data
224  * @v len Length of data
225  * @ret rc Return status code
226  */
227 static int netvsc_rx_established_buffer ( struct netvsc_device *netvsc,
228  const void *data, size_t len ) {
229  const struct netvsc_rx_establish_buffer_completion *cmplt = data;
230 
231  /* Check completion */
232  if ( len < sizeof ( *cmplt ) ) {
233  DBGC ( netvsc, "NETVSC %s underlength buffer completion (%zd "
234  "bytes)\n", netvsc->name, len );
235  return -EINVAL;
236  }
237  if ( cmplt->header.type != cpu_to_le32 ( NETVSC_RX_ESTABLISH_CMPLT ) ) {
238  DBGC ( netvsc, "NETVSC %s unexpected buffer completion type "
239  "%d\n", netvsc->name, le32_to_cpu ( cmplt->header.type));
240  return -EPROTO;
241  }
242  if ( cmplt->status != cpu_to_le32 ( NETVSC_OK ) ) {
243  DBGC ( netvsc, "NETVSC %s buffer failure status %d\n",
244  netvsc->name, le32_to_cpu ( cmplt->status ) );
245  return -EPROTO;
246  }
247 
248  return 0;
249 }
250 
251 /**
252  * Revoke data buffer
253  *
254  * @v netvsc NetVSC device
255  * @v buffer Data buffer
256  * @ret rc Return status code
257  */
258 static int netvsc_revoke_buffer ( struct netvsc_device *netvsc,
259  struct netvsc_buffer *buffer ) {
261  int rc;
262 
263  /* If the buffer's GPADL is obsolete (i.e. was created before
264  * the most recent Hyper-V reset), then we will never receive
265  * a response to the revoke message. Since the GPADL is
266  * already destroyed as far as the hypervisor is concerned, no
267  * further action is required.
268  */
269  if ( netvsc_is_obsolete ( netvsc ) )
270  return 0;
271 
272  /* Construct message */
273  memset ( &msg, 0, sizeof ( msg ) );
274  msg.header.type = cpu_to_le32 ( buffer->revoke_type );
275  msg.pageset = buffer->pages.pageset; /* Already protocol-endian */
276 
277  /* Send message and wait for completion */
278  if ( ( rc = netvsc_control ( netvsc, buffer->revoke_xrid,
279  &msg, sizeof ( msg ) ) ) != 0 ) {
280  DBGC ( netvsc, "NETVSC %s could not revoke buffer: %s\n",
281  netvsc->name, strerror ( rc ) );
282  return rc;
283  }
284 
285  return 0;
286 }
287 
288 /**
289  * Handle received control packet
290  *
291  * @v vmdev VMBus device
292  * @v xid Transaction ID
293  * @v data Data
294  * @v len Length of data
295  * @ret rc Return status code
296  */
297 static int netvsc_recv_control ( struct vmbus_device *vmdev, uint64_t xid,
298  const void *data, size_t len ) {
299  struct rndis_device *rndis = vmbus_get_drvdata ( vmdev );
300  struct netvsc_device *netvsc = rndis->priv;
301 
302  DBGC ( netvsc, "NETVSC %s received unsupported control packet "
303  "(%08llx):\n", netvsc->name, xid );
304  DBGC_HDA ( netvsc, 0, data, len );
305  return -ENOTSUP;
306 }
307 
308 /**
309  * Handle received data packet
310  *
311  * @v vmdev VMBus device
312  * @v xid Transaction ID
313  * @v data Data
314  * @v len Length of data
315  * @v list List of I/O buffers
316  * @ret rc Return status code
317  */
318 static int netvsc_recv_data ( struct vmbus_device *vmdev, uint64_t xid,
319  const void *data, size_t len,
320  struct list_head *list ) {
321  struct rndis_device *rndis = vmbus_get_drvdata ( vmdev );
322  struct netvsc_device *netvsc = rndis->priv;
323  const struct netvsc_rndis_message *msg = data;
324  struct io_buffer *iobuf;
325  struct io_buffer *tmp;
326  int rc;
327 
328  /* Sanity check */
329  if ( len < sizeof ( *msg ) ) {
330  DBGC ( netvsc, "NETVSC %s received underlength RNDIS packet "
331  "(%zd bytes)\n", netvsc->name, len );
332  rc = -EINVAL;
333  goto err_sanity;
334  }
335  if ( msg->header.type != cpu_to_le32 ( NETVSC_RNDIS_MSG ) ) {
336  DBGC ( netvsc, "NETVSC %s received unexpected RNDIS packet "
337  "type %d\n", netvsc->name,
338  le32_to_cpu ( msg->header.type ) );
339  rc = -EINVAL;
340  goto err_sanity;
341  }
342 
343  /* Send completion back to host */
344  if ( ( rc = vmbus_send_completion ( vmdev, xid, NULL, 0 ) ) != 0 ) {
345  DBGC ( netvsc, "NETVSC %s could not send completion: %s\n",
346  netvsc->name, strerror ( rc ) );
347  goto err_completion;
348  }
349 
350  /* Hand off to RNDIS */
351  list_for_each_entry_safe ( iobuf, tmp, list, list ) {
352  list_del ( &iobuf->list );
353  rndis_rx ( rndis, iob_disown ( iobuf ) );
354  }
355 
356  return 0;
357 
358  err_completion:
359  err_sanity:
360  list_for_each_entry_safe ( iobuf, tmp, list, list ) {
361  list_del ( &iobuf->list );
362  free_iob ( iobuf );
363  }
364  return rc;
365 }
366 
367 /**
368  * Handle received completion packet
369  *
370  * @v vmdev VMBus device
371  * @v xid Transaction ID
372  * @v data Data
373  * @v len Length of data
374  * @ret rc Return status code
375  */
376 static int netvsc_recv_completion ( struct vmbus_device *vmdev, uint64_t xid,
377  const void *data, size_t len ) {
378  struct rndis_device *rndis = vmbus_get_drvdata ( vmdev );
379  struct netvsc_device *netvsc = rndis->priv;
380  struct io_buffer *iobuf;
381  int ( * completion ) ( struct netvsc_device *netvsc,
382  const void *data, size_t len );
383  unsigned int xrid = ( xid - NETVSC_BASE_XID );
384  unsigned int tx_id;
385  int rc;
386 
387  /* Handle transmit completion, if applicable */
388  tx_id = ( xrid - NETVSC_TX_BASE_XRID );
389  if ( ( tx_id < NETVSC_TX_NUM_DESC ) &&
390  ( ( iobuf = netvsc->tx.iobufs[tx_id] ) != NULL ) ) {
391 
392  /* Free buffer ID */
393  netvsc->tx.iobufs[tx_id] = NULL;
394  netvsc->tx.ids[ ( netvsc->tx.id_cons++ ) &
395  ( netvsc->tx.count - 1 ) ] = tx_id;
396 
397  /* Hand back to RNDIS */
398  rndis_tx_complete ( rndis, iobuf );
399  return 0;
400  }
401 
402  /* Otherwise determine completion handler */
403  if ( xrid == NETVSC_INIT_XRID ) {
405  } else if ( xrid == NETVSC_RX_ESTABLISH_XRID ) {
407  } else if ( ( netvsc->wait_xrid != 0 ) &&
408  ( xrid == netvsc->wait_xrid ) ) {
410  } else {
411  DBGC ( netvsc, "NETVSC %s received unexpected completion "
412  "(%08llx)\n", netvsc->name, xid );
413  return -EPIPE;
414  }
415 
416  /* Hand off to completion handler */
417  rc = completion ( netvsc, data, len );
418 
419  /* Record completion handler result if applicable */
420  if ( xrid == netvsc->wait_xrid ) {
421  netvsc->wait_xrid = 0;
422  netvsc->wait_rc = rc;
423  }
424 
425  return rc;
426 }
427 
428 /**
429  * Handle received cancellation packet
430  *
431  * @v vmdev VMBus device
432  * @v xid Transaction ID
433  * @ret rc Return status code
434  */
436  uint64_t xid ) {
437  struct rndis_device *rndis = vmbus_get_drvdata ( vmdev );
438  struct netvsc_device *netvsc = rndis->priv;
439 
440  DBGC ( netvsc, "NETVSC %s received unsupported cancellation packet "
441  "(%08llx):\n", netvsc->name, xid );
442  return -ENOTSUP;
443 }
444 
445 /** VMBus channel operations */
448  .recv_data = netvsc_recv_data,
449  .recv_completion = netvsc_recv_completion,
450  .recv_cancellation = netvsc_recv_cancellation,
451 };
452 
453 /**
454  * Poll for completed and received packets
455  *
456  * @v rndis RNDIS device
457  */
458 static void netvsc_poll ( struct rndis_device *rndis ) {
459  struct netvsc_device *netvsc = rndis->priv;
460  struct vmbus_device *vmdev = netvsc->vmdev;
461 
462  /* Poll VMBus device */
463  while ( vmbus_has_data ( vmdev ) )
464  vmbus_poll ( vmdev );
465 }
466 
467 /**
468  * Transmit packet
469  *
470  * @v rndis RNDIS device
471  * @v iobuf I/O buffer
472  * @ret rc Return status code
473  *
474  * If this method returns success then the RNDIS device must
475  * eventually report completion via rndis_tx_complete().
476  */
477 static int netvsc_transmit ( struct rndis_device *rndis,
478  struct io_buffer *iobuf ) {
479  struct netvsc_device *netvsc = rndis->priv;
480  struct rndis_header *header = iobuf->data;
481  struct netvsc_rndis_message msg;
482  unsigned int tx_id;
483  unsigned int xrid;
484  uint64_t xid;
485  int rc;
486 
487  /* If the device is obsolete (i.e. was opened before the most
488  * recent Hyper-V reset), then we will never receive transmit
489  * completions. Fail transmissions immediately to minimise
490  * the delay in closing and reopening the device.
491  */
492  if ( netvsc_is_obsolete ( netvsc ) )
493  return -EPIPE;
494 
495  /* Sanity check */
496  assert ( iob_len ( iobuf ) >= sizeof ( *header ) );
497  assert ( iob_len ( iobuf ) == le32_to_cpu ( header->len ) );
498 
499  /* Check that we have space in the transmit ring */
500  if ( netvsc_ring_is_full ( &netvsc->tx ) )
501  return rndis_tx_defer ( rndis, iobuf );
502 
503  /* Allocate buffer ID and calculate transaction ID */
504  tx_id = netvsc->tx.ids[ netvsc->tx.id_prod & ( netvsc->tx.count - 1 ) ];
505  assert ( netvsc->tx.iobufs[tx_id] == NULL );
506  xrid = ( NETVSC_TX_BASE_XRID + tx_id );
507  xid = ( NETVSC_BASE_XID + xrid );
508 
509  /* Construct message */
510  memset ( &msg, 0, sizeof ( msg ) );
511  msg.header.type = cpu_to_le32 ( NETVSC_RNDIS_MSG );
512  msg.channel = ( ( header->type == cpu_to_le32 ( RNDIS_PACKET_MSG ) ) ?
515 
516  /* Send message */
517  if ( ( rc = vmbus_send_data ( netvsc->vmdev, xid, &msg, sizeof ( msg ),
518  iobuf ) ) != 0 ) {
519  DBGC ( netvsc, "NETVSC %s could not send RNDIS message: %s\n",
520  netvsc->name, strerror ( rc ) );
521  return rc;
522  }
523 
524  /* Store I/O buffer and consume buffer ID */
525  netvsc->tx.iobufs[tx_id] = iobuf;
526  netvsc->tx.id_prod++;
527 
528  return 0;
529 }
530 
531 /**
532  * Cancel transmission
533  *
534  * @v netvsc NetVSC device
535  * @v iobuf I/O buffer
536  * @v tx_id Transmission ID
537  */
538 static void netvsc_cancel_transmit ( struct netvsc_device *netvsc,
539  struct io_buffer *iobuf,
540  unsigned int tx_id ) {
541  unsigned int xrid;
542  uint64_t xid;
543 
544  /* Send cancellation */
545  xrid = ( NETVSC_TX_BASE_XRID + tx_id );
546  xid = ( NETVSC_BASE_XID + xrid );
547  DBGC ( netvsc, "NETVSC %s cancelling transmission %#x\n",
548  netvsc->name, tx_id );
549  vmbus_send_cancellation ( netvsc->vmdev, xid );
550 
551  /* Report back to RNDIS */
552  rndis_tx_complete_err ( netvsc->rndis, iobuf, -ECANCELED );
553 }
554 
555 /**
556  * Create descriptor ring
557  *
558  * @v netvsc NetVSC device
559  * @v ring Descriptor ring
560  * @ret rc Return status code
561  */
562 static int netvsc_create_ring ( struct netvsc_device *netvsc __unused,
563  struct netvsc_ring *ring ) {
564  unsigned int i;
565 
566  /* Initialise buffer ID ring */
567  for ( i = 0 ; i < ring->count ; i++ ) {
568  ring->ids[i] = i;
569  assert ( ring->iobufs[i] == NULL );
570  }
571  ring->id_prod = 0;
572  ring->id_cons = 0;
573 
574  return 0;
575 }
576 
577 /**
578  * Destroy descriptor ring
579  *
580  * @v netvsc NetVSC device
581  * @v ring Descriptor ring
582  * @v discard Method used to discard outstanding buffer, or NULL
583  */
584 static void netvsc_destroy_ring ( struct netvsc_device *netvsc,
585  struct netvsc_ring *ring,
586  void ( * discard ) ( struct netvsc_device *,
587  struct io_buffer *,
588  unsigned int ) ) {
589  struct io_buffer *iobuf;
590  unsigned int i;
591 
592  /* Flush any outstanding buffers */
593  for ( i = 0 ; i < ring->count ; i++ ) {
594  iobuf = ring->iobufs[i];
595  if ( ! iobuf )
596  continue;
597  ring->iobufs[i] = NULL;
598  ring->ids[ ( ring->id_cons++ ) & ( ring->count - 1 ) ] = i;
599  if ( discard )
600  discard ( netvsc, iobuf, i );
601  }
602 
603  /* Sanity check */
604  assert ( netvsc_ring_is_empty ( ring ) );
605 }
606 
607 /**
608  * Copy data from data buffer
609  *
610  * @v pages Transfer page set
611  * @v data Data buffer
612  * @v offset Offset within page set
613  * @v len Length within page set
614  * @ret rc Return status code
615  */
616 static int netvsc_buffer_copy ( struct vmbus_xfer_pages *pages, void *data,
617  size_t offset, size_t len ) {
618  struct netvsc_buffer *buffer =
619  container_of ( pages, struct netvsc_buffer, pages );
620 
621  /* Sanity check */
622  if ( ( offset > buffer->len ) || ( len > ( buffer->len - offset ) ) )
623  return -ERANGE;
624 
625  /* Copy data from buffer */
626  memcpy ( data, ( buffer->data + offset ), len );
627 
628  return 0;
629 }
630 
631 /** Transfer page set operations */
634 };
635 
636 /**
637  * Create data buffer
638  *
639  * @v netvsc NetVSC device
640  * @v buffer Data buffer
641  * @ret rc Return status code
642  */
643 static int netvsc_create_buffer ( struct netvsc_device *netvsc,
644  struct netvsc_buffer *buffer ) {
645  struct vmbus_device *vmdev = netvsc->vmdev;
646  int gpadl;
647  int rc;
648 
649  /* Allocate receive buffer */
650  buffer->data = umalloc ( buffer->len );
651  if ( ! buffer->data ) {
652  DBGC ( netvsc, "NETVSC %s could not allocate %zd-byte buffer\n",
653  netvsc->name, buffer->len );
654  rc = -ENOMEM;
655  goto err_alloc;
656  }
657 
658  /* Establish GPA descriptor list */
659  gpadl = vmbus_establish_gpadl ( vmdev, buffer->data, buffer->len );
660  if ( gpadl < 0 ) {
661  rc = gpadl;
662  DBGC ( netvsc, "NETVSC %s could not establish GPADL: %s\n",
663  netvsc->name, strerror ( rc ) );
664  goto err_establish_gpadl;
665  }
666  buffer->gpadl = gpadl;
667 
668  /* Register transfer page set */
669  if ( ( rc = vmbus_register_pages ( vmdev, &buffer->pages ) ) != 0 ) {
670  DBGC ( netvsc, "NETVSC %s could not register transfer pages: "
671  "%s\n", netvsc->name, strerror ( rc ) );
672  goto err_register_pages;
673  }
674 
675  return 0;
676 
677  vmbus_unregister_pages ( vmdev, &buffer->pages );
678  err_register_pages:
679  vmbus_gpadl_teardown ( vmdev, gpadl );
680  err_establish_gpadl:
681  ufree ( buffer->data );
682  err_alloc:
683  return rc;
684 }
685 
686 /**
687  * Destroy data buffer
688  *
689  * @v netvsc NetVSC device
690  * @v buffer Data buffer
691  */
692 static void netvsc_destroy_buffer ( struct netvsc_device *netvsc,
693  struct netvsc_buffer *buffer ) {
694  struct vmbus_device *vmdev = netvsc->vmdev;
695  int rc;
696 
697  /* Unregister transfer pages */
698  vmbus_unregister_pages ( vmdev, &buffer->pages );
699 
700  /* Tear down GPA descriptor list */
701  if ( ( rc = vmbus_gpadl_teardown ( vmdev, buffer->gpadl ) ) != 0 ) {
702  DBGC ( netvsc, "NETVSC %s could not tear down GPADL: %s\n",
703  netvsc->name, strerror ( rc ) );
704  /* Death is imminent. The host may well continue to
705  * write to the data buffer. The best we can do is
706  * leak memory for now and hope that the host doesn't
707  * write to this region after we load an OS.
708  */
709  return;
710  }
711 
712  /* Free buffer */
713  ufree ( buffer->data );
714 }
715 
716 /**
717  * Open device
718  *
719  * @v rndis RNDIS device
720  * @ret rc Return status code
721  */
722 static int netvsc_open ( struct rndis_device *rndis ) {
723  struct netvsc_device *netvsc = rndis->priv;
724  int rc;
725 
726  /* Initialise receive buffer */
727  if ( ( rc = netvsc_create_buffer ( netvsc, &netvsc->rx ) ) != 0 )
728  goto err_create_rx;
729 
730  /* Open channel */
731  if ( ( rc = vmbus_open ( netvsc->vmdev, &netvsc_channel_operations,
732  PAGE_SIZE, PAGE_SIZE, NETVSC_MTU ) ) != 0 ) {
733  DBGC ( netvsc, "NETVSC %s could not open VMBus: %s\n",
734  netvsc->name, strerror ( rc ) );
735  goto err_vmbus_open;
736  }
737 
738  /* Initialise communication with NetVSP */
739  if ( ( rc = netvsc_initialise ( netvsc ) ) != 0 )
740  goto err_initialise;
741  if ( ( rc = netvsc_ndis_version ( netvsc ) ) != 0 )
742  goto err_ndis_version;
743 
744  /* Initialise transmit ring */
745  if ( ( rc = netvsc_create_ring ( netvsc, &netvsc->tx ) ) != 0 )
746  goto err_create_tx;
747 
748  /* Establish receive buffer */
749  if ( ( rc = netvsc_establish_buffer ( netvsc, &netvsc->rx ) ) != 0 )
750  goto err_establish_rx;
751 
752  return 0;
753 
754  netvsc_revoke_buffer ( netvsc, &netvsc->rx );
755  err_establish_rx:
756  netvsc_destroy_ring ( netvsc, &netvsc->tx, NULL );
757  err_create_tx:
758  err_ndis_version:
759  err_initialise:
760  vmbus_close ( netvsc->vmdev );
761  err_vmbus_open:
762  netvsc_destroy_buffer ( netvsc, &netvsc->rx );
763  err_create_rx:
764  return rc;
765 }
766 
767 /**
768  * Close device
769  *
770  * @v rndis RNDIS device
771  */
772 static void netvsc_close ( struct rndis_device *rndis ) {
773  struct netvsc_device *netvsc = rndis->priv;
774 
775  /* Revoke receive buffer */
776  netvsc_revoke_buffer ( netvsc, &netvsc->rx );
777 
778  /* Destroy transmit ring */
779  netvsc_destroy_ring ( netvsc, &netvsc->tx, netvsc_cancel_transmit );
780 
781  /* Close channel */
782  vmbus_close ( netvsc->vmdev );
783 
784  /* Destroy receive buffer */
785  netvsc_destroy_buffer ( netvsc, &netvsc->rx );
786 }
787 
788 /** RNDIS operations */
790  .open = netvsc_open,
791  .close = netvsc_close,
792  .transmit = netvsc_transmit,
793  .poll = netvsc_poll,
794 };
795 
796 /**
797  * Probe device
798  *
799  * @v vmdev VMBus device
800  * @ret rc Return status code
801  */
802 static int netvsc_probe ( struct vmbus_device *vmdev ) {
803  struct netvsc_device *netvsc;
804  struct rndis_device *rndis;
805  int rc;
806 
807  /* Allocate and initialise structure */
808  rndis = alloc_rndis ( sizeof ( *netvsc ) );
809  if ( ! rndis ) {
810  rc = -ENOMEM;
811  goto err_alloc;
812  }
813  rndis_init ( rndis, &netvsc_operations );
814  rndis->netdev->dev = &vmdev->dev;
815  netvsc = rndis->priv;
816  netvsc->vmdev = vmdev;
817  netvsc->rndis = rndis;
818  netvsc->name = vmdev->dev.name;
819  netvsc_init_ring ( &netvsc->tx, NETVSC_TX_NUM_DESC,
820  netvsc->tx_iobufs, netvsc->tx_ids );
821  netvsc_init_buffer ( &netvsc->rx, NETVSC_RX_BUF_PAGESET,
826  vmbus_set_drvdata ( vmdev, rndis );
827 
828  /* Register RNDIS device */
829  if ( ( rc = register_rndis ( rndis ) ) != 0 ) {
830  DBGC ( netvsc, "NETVSC %s could not register: %s\n",
831  netvsc->name, strerror ( rc ) );
832  goto err_register;
833  }
834 
835  return 0;
836 
837  unregister_rndis ( rndis );
838  err_register:
839  free_rndis ( rndis );
840  err_alloc:
841  return rc;
842 }
843 
844 /**
845  * Reset device
846  *
847  * @v vmdev VMBus device
848  * @ret rc Return status code
849  */
850 static int netvsc_reset ( struct vmbus_device *vmdev ) {
851  struct rndis_device *rndis = vmbus_get_drvdata ( vmdev );
852  struct netvsc_device *netvsc = rndis->priv;
853  struct net_device *netdev = rndis->netdev;
854  int rc;
855 
856  /* A closed device holds no NetVSC (or RNDIS) state, so there
857  * is nothing to reset.
858  */
859  if ( ! netdev_is_open ( netdev ) )
860  return 0;
861 
862  /* Close and reopen device to reset any stale state */
863  netdev_close ( netdev );
864  if ( ( rc = netdev_open ( netdev ) ) != 0 ) {
865  DBGC ( netvsc, "NETVSC %s could not reopen: %s\n",
866  netvsc->name, strerror ( rc ) );
867  return rc;
868  }
869 
870  return 0;
871 }
872 
873 /**
874  * Remove device
875  *
876  * @v vmdev VMBus device
877  */
878 static void netvsc_remove ( struct vmbus_device *vmdev ) {
879  struct rndis_device *rndis = vmbus_get_drvdata ( vmdev );
880 
881  /* Unregister RNDIS device */
882  unregister_rndis ( rndis );
883 
884  /* Free RNDIS device */
885  free_rndis ( rndis );
886 }
887 
888 /** NetVSC driver */
889 struct vmbus_driver netvsc_driver __vmbus_driver = {
890  .name = "netvsc",
891  .type = VMBUS_TYPE ( 0xf8615163, 0xdf3e, 0x46c5, 0x913f,
892  0xf2, 0xd2, 0xf9, 0x65, 0xed, 0x0e ),
893  .probe = netvsc_probe,
894  .reset = netvsc_reset,
895  .remove = netvsc_remove,
896 };
struct rndis_device * alloc_rndis(size_t priv_len)
Allocate RNDIS device.
Definition: rndis.c:1000
unsigned int count
Number of descriptors.
Definition: netvsc.h:238
static __always_inline void ufree(void *ptr)
Free external memory.
Definition: umalloc.h:67
#define EINVAL
Invalid argument.
Definition: errno.h:428
NDIS version.
Definition: netvsc.h:54
static int netvsc_create_ring(struct netvsc_device *netvsc __unused, struct netvsc_ring *ring)
Create descriptor ring.
Definition: netvsc.c:562
static int netvsc_transmit(struct rndis_device *rndis, struct io_buffer *iobuf)
Transmit packet.
Definition: netvsc.c:477
NetVSC initialisation message.
Definition: netvsc.h:83
const char * name
Name.
Definition: vmbus.h:522
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
int vmbus_send_completion(struct vmbus_device *vmdev, uint64_t xid, const void *data, size_t len)
Send completion packet via ring buffer.
Definition: vmbus.c:834
#define NETVSC_RX_ESTABLISH_CMPLT
NetVSC establish receive data buffer completion.
Definition: netvsc.h:139
static struct vmbus_channel_operations netvsc_channel_operations
VMBus channel operations.
Definition: netvsc.c:446
struct device dev
Generic iPXE device.
Definition: vmbus.h:477
static int vmbus_has_data(struct vmbus_device *vmdev)
Check if data is present in ring buffer.
Definition: vmbus.h:585
int(* open)(struct rndis_device *rndis)
Open RNDIS device.
Definition: rndis.h:289
#define NETVSC_RNDIS_DATA
RNDIS data channel (for RNDIS_PACKET_MSG only)
Definition: netvsc.h:227
void msg(unsigned int row, const char *fmt,...)
Print message centred on specified row.
Definition: message.c:61
static void netvsc_poll(struct rndis_device *rndis)
Poll for completed and received packets.
Definition: netvsc.c:458
pseudo_bit_t completion[0x00001]
Definition: arbel.h:13
static void netvsc_close(struct rndis_device *rndis)
Close device.
Definition: netvsc.c:772
static void netvsc_cancel_transmit(struct netvsc_device *netvsc, struct io_buffer *iobuf, unsigned int tx_id)
Cancel transmission.
Definition: netvsc.c:538
#define le32_to_cpu(value)
Definition: byteswap.h:113
int(* recv_control)(struct vmbus_device *vmdev, uint64_t xid, const void *data, size_t len)
Handle received control packet.
Definition: vmbus.h:406
Error codes.
static void netvsc_destroy_ring(struct netvsc_device *netvsc, struct netvsc_ring *ring, void(*discard)(struct netvsc_device *, struct io_buffer *, unsigned int))
Destroy descriptor ring.
Definition: netvsc.c:584
struct vmbus_driver netvsc_driver __vmbus_driver
NetVSC driver.
Definition: netvsc.c:889
static void rndis_tx_complete(struct rndis_device *rndis, struct io_buffer *iobuf)
Complete message transmission.
Definition: rndis.h:364
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:152
int vmbus_open(struct vmbus_device *vmdev, struct vmbus_channel_operations *op, size_t out_len, size_t in_len, size_t mtu)
Open VMBus channel.
Definition: vmbus.c:403
#define EPIPE
Broken pipe.
Definition: errno.h:619
void unregister_rndis(struct rndis_device *rndis)
Unregister RNDIS device.
Definition: rndis.c:1054
NetVSC RNDIS message.
Definition: netvsc.h:213
#define DBGC(...)
Definition: compiler.h:505
#define NETVSC_VERSION_1
Oldest known NetVSC protocol version.
Definition: netvsc.h:95
char name[40]
Name.
Definition: device.h:78
static int netvsc_establish_buffer(struct netvsc_device *netvsc, struct netvsc_buffer *buffer)
Establish data buffer.
Definition: netvsc.c:197
A VMBus device.
Definition: vmbus.h:475
unsigned long long uint64_t
Definition: stdint.h:13
A NetVSC data buffer.
Definition: netvsc.h:294
#define NETVSC_RNDIS_MSG
NetVSC RNDIS message.
Definition: netvsc.h:210
Establish receive buffer.
Definition: netvsc.h:56
unsigned int id_cons
Buffer ID consumer counter.
Definition: netvsc.h:246
uint32_t buffer
Buffer index (or NETVSC_RNDIS_NO_BUFFER)
Definition: netvsc.h:16
static int netvsc_recv_cancellation(struct vmbus_device *vmdev, uint64_t xid)
Handle received cancellation packet.
Definition: netvsc.c:435
#define PAGE_SIZE
Page size.
Definition: io.h:27
const char * name
Name.
Definition: netvsc.h:347
struct netvsc_header header
Message header.
Definition: netvsc.h:103
NetVSC establish receive data buffer completion.
Definition: netvsc.h:178
static void netvsc_remove(struct vmbus_device *vmdev)
Remove device.
Definition: netvsc.c:878
#define NETVSC_RX_REVOKE_MSG
NetVSC revoke receive data buffer message.
Definition: netvsc.h:142
#define ECANCELED
Operation canceled.
Definition: errno.h:343
#define ENOTSUP
Operation not supported.
Definition: errno.h:589
#define NETVSC_RX_BUF_PAGESET
RX data buffer page set ID.
Definition: netvsc.h:33
A doubly-linked list entry (or list head)
Definition: list.h:18
static int vmbus_register_pages(struct vmbus_device *vmdev, struct vmbus_xfer_pages *pages)
Register transfer page set.
Definition: vmbus.h:598
Hyper-V network virtual service client.
int vmbus_establish_gpadl(struct vmbus_device *vmdev, void *data, size_t len)
Establish GPA descriptor list.
Definition: vmbus.c:276
#define NETVSC_NDIS_MINOR
NetVSC NDIS minor version.
Definition: netvsc.h:133
Hyper-V virtual machine bus.
unsigned long tmp
Definition: linux_pci.h:64
static int netvsc_revoke_buffer(struct netvsc_device *netvsc, struct netvsc_buffer *buffer)
Revoke data buffer.
Definition: netvsc.c:258
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
#define ENOMEM
Not enough space.
Definition: errno.h:534
#define iob_disown(iobuf)
Disown an I/O buffer.
Definition: iobuf.h:216
void * memcpy(void *dest, const void *src, size_t len) __nonnull
struct io_buffer ** iobufs
I/O buffers, indexed by buffer ID.
Definition: netvsc.h:240
static int netdev_is_open(struct net_device *netdev)
Check whether or not network device is open.
Definition: netdevice.h:661
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
unsigned int id_prod
Buffer ID producer counter.
Definition: netvsc.h:244
#define NETVSC_MAX_WAIT_MS
Maximum time to wait for a transaction to complete.
Definition: netvsc.h:19
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:35
struct net_device * netdev
Network device.
Definition: rndis.h:319
NetVSC establish data buffer message.
Definition: netvsc.h:154
static int netvsc_recv_completion(struct vmbus_device *vmdev, uint64_t xid, const void *data, size_t len)
Handle received completion packet.
Definition: netvsc.c:376
#define NETVSC_RNDIS_NO_BUFFER
"No buffer used" index
Definition: netvsc.h:233
#define DBGC_HDA(...)
Definition: compiler.h:506
#define __unused
Declare a variable or data structure as unused.
Definition: compiler.h:573
#define NETVSC_RX_ESTABLISH_MSG
NetVSC establish receive data buffer message.
Definition: netvsc.h:136
static int netvsc_recv_control(struct vmbus_device *vmdev, uint64_t xid, const void *data, size_t len)
Handle received control packet.
Definition: netvsc.c:297
ring len
Length.
Definition: dwmac.h:231
An RNDIS device.
Definition: rndis.h:317
static struct net_device * netdev
Definition: gdbudp.c:52
struct netvsc_ring tx
Transmit ring.
Definition: netvsc.h:350
#define NETVSC_INIT_CMPLT
NetVSC initialisation completion.
Definition: netvsc.h:98
static int netvsc_buffer_copy(struct vmbus_xfer_pages *pages, void *data, size_t offset, size_t len)
Copy data from data buffer.
Definition: netvsc.c:616
#define list_for_each_entry_safe(pos, tmp, head, member)
Iterate over entries in a list, safe against deletion of the current entry.
Definition: list.h:458
static struct rndis_operations netvsc_operations
RNDIS operations.
Definition: netvsc.c:789
#define cpu_to_le32(value)
Definition: byteswap.h:107
#define EPROTO
Protocol error.
Definition: errno.h:624
A NetVSC device.
Definition: netvsc.h:341
Revoke receive buffer.
Definition: netvsc.h:58
#define ERANGE
Result too large.
Definition: errno.h:639
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
int register_rndis(struct rndis_device *rndis)
Register RNDIS device.
Definition: rndis.c:1026
static void * vmbus_get_drvdata(struct vmbus_device *vmdev)
Get VMBus device driver-private data.
Definition: vmbus.h:566
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:159
A VMBus device driver.
Definition: vmbus.h:520
User memory allocation.
A network device.
Definition: netdevice.h:352
static int netvsc_open(struct rndis_device *rndis)
Open device.
Definition: netvsc.c:722
#define NETVSC_MTU
Maximum supported NetVSC message length.
Definition: netvsc.h:13
static int netvsc_ndis_version(struct netvsc_device *netvsc)
Set NDIS version.
Definition: netvsc.c:169
static int netvsc_completed(struct netvsc_device *netvsc __unused, const void *data __unused, size_t len __unused)
Handle generic completion.
Definition: netvsc.c:97
uint32_t type
Type.
Definition: netvsc.h:76
uint32_t status
Status.
Definition: netvsc.h:109
Remote Network Driver Interface Specification.
uint32_t gpadl
GPADL ID.
Definition: netvsc.h:14
static void vmbus_unregister_pages(struct vmbus_device *vmdev, struct vmbus_xfer_pages *pages)
Unregister transfer page set.
Definition: vmbus.h:612
RNDIS device operations.
Definition: rndis.h:282
int vmbus_gpadl_teardown(struct vmbus_device *vmdev, unsigned int gpadl)
Tear down GPA descriptor list.
Definition: vmbus.c:347
#define NETVSC_NDIS_MAJOR
NetVSC NDIS major version.
Definition: netvsc.h:130
void rndis_rx(struct rndis_device *rndis, struct io_buffer *iobuf)
Receive packet from underlying transport layer.
Definition: rndis.c:829
struct vmbus_xfer_pages pages
Transfer page set.
Definition: netvsc.h:296
static int netvsc_rx_established_buffer(struct netvsc_device *netvsc, const void *data, size_t len)
Handle establish receive data buffer completion.
Definition: netvsc.c:227
static void rndis_init(struct rndis_device *rndis, struct rndis_operations *op)
Initialise an RNDIS device.
Definition: rndis.h:339
struct io_buffer * tx_iobufs[NETVSC_TX_NUM_DESC]
Transmit I/O buffers.
Definition: netvsc.h:354
#define NETVSC_NDIS_VERSION_MSG
NetVSC NDIS version message.
Definition: netvsc.h:115
#define NETVSC_TX_NUM_DESC
Number of transmit ring entries.
Definition: netvsc.h:27
int(* copy)(struct vmbus_xfer_pages *pages, void *data, size_t offset, size_t len)
Copy data from transfer page.
Definition: vmbus.h:460
int rndis_tx_defer(struct rndis_device *rndis, struct io_buffer *iobuf)
Defer transmitted packet.
Definition: rndis.c:190
struct device * dev
Underlying hardware device.
Definition: netdevice.h:364
int vmbus_send_cancellation(struct vmbus_device *vmdev, uint64_t xid)
Send cancellation packet via ring buffer.
Definition: vmbus.c:857
void netdev_close(struct net_device *netdev)
Close network device.
Definition: netdevice.c:895
int vmbus_poll(struct vmbus_device *vmdev)
Poll ring buffer.
Definition: vmbus.c:972
uint8_t tx_ids[NETVSC_TX_NUM_DESC]
Transmit buffer IDs.
Definition: netvsc.h:352
unsigned int wait_xrid
Relative transaction ID for current blocking transaction.
Definition: netvsc.h:360
RNDIS message header.
Definition: rndis.h:23
A NetVSC descriptor ring.
Definition: netvsc.h:236
#define VMBUS_TYPE(a, b, c, d, e0, e1, e2, e3, e4, e5)
Construct VMBus type.
Definition: vmbus.h:571
void mdelay(unsigned long msecs)
Delay for a fixed number of milliseconds.
Definition: timer.c:78
VMBus transfer page set operations.
Definition: vmbus.h:450
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
int vmbus_send_control(struct vmbus_device *vmdev, uint64_t xid, const void *data, size_t len)
Send control packet via ring buffer.
Definition: vmbus.c:765
VMBus transfer page set.
Definition: vmbus.h:465
struct vmbus_device * vmdev
VMBus device.
Definition: netvsc.h:343
struct list_head list
List of which this buffer is a member.
Definition: iobuf.h:44
static int netvsc_reset(struct vmbus_device *vmdev)
Reset device.
Definition: netvsc.c:850
static void netvsc_destroy_buffer(struct netvsc_device *netvsc, struct netvsc_buffer *buffer)
Destroy data buffer.
Definition: netvsc.c:692
VMBus channel operations.
Definition: vmbus.h:396
void * data
Start of data.
Definition: iobuf.h:52
static __always_inline void * umalloc(size_t size)
Allocate external memory.
Definition: umalloc.h:56
void * priv
Driver private data.
Definition: rndis.h:325
struct ena_llq_option header
Header locations.
Definition: ena.h:16
#define RNDIS_PACKET_MSG
RNDIS packet message.
Definition: rndis.h:219
uint8_t data[48]
Additional event data.
Definition: ena.h:22
NetVSC NDIS version message.
Definition: netvsc.h:118
static int netvsc_initialised(struct netvsc_device *netvsc, const void *data, size_t len)
Handle initialisation completion.
Definition: netvsc.c:138
Initialisation.
Definition: netvsc.h:52
static int netvsc_probe(struct vmbus_device *vmdev)
Probe device.
Definition: netvsc.c:802
#define NETVSC_BASE_XID
Base transaction ID.
Definition: netvsc.h:45
static int netvsc_control(struct netvsc_device *netvsc, unsigned int xrid, const void *data, size_t len)
Send control message and wait for completion.
Definition: netvsc.c:53
NetVSC revoke data buffer message.
Definition: netvsc.h:200
VMBus "GPADL teardown" message.
Definition: vmbus.h:193
void vmbus_close(struct vmbus_device *vmdev)
Close VMBus channel.
Definition: vmbus.c:524
Transmit descriptors (one per transmit buffer ID)
Definition: netvsc.h:50
uint16_t offset
Offset to command line.
Definition: bzimage.h:8
#define NETVSC_RX_BUF_LEN
RX data buffer length.
Definition: netvsc.h:39
#define NETVSC_INIT_MSG
NetVSC initialisation message.
Definition: netvsc.h:80
static void vmbus_set_drvdata(struct vmbus_device *vmdev, void *priv)
Set VMBus device driver-private data.
Definition: vmbus.h:556
static struct vmbus_xfer_pages_operations netvsc_xfer_pages_operations
Transfer page set operations.
Definition: netvsc.c:632
void vmbus_dump_channel(struct vmbus_device *vmdev)
Dump channel status (for debugging)
Definition: vmbus.c:1089
static int netvsc_initialise(struct netvsc_device *netvsc)
Initialise communication.
Definition: netvsc.c:108
struct rndis_device * rndis
RNDIS device.
Definition: netvsc.h:345
void free_rndis(struct rndis_device *rndis)
Free RNDIS device.
Definition: rndis.c:1066
void rndis_tx_complete_err(struct rndis_device *rndis, struct io_buffer *iobuf, int rc)
Complete message transmission.
Definition: rndis.c:127
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
int vmbus_send_data(struct vmbus_device *vmdev, uint64_t xid, const void *data, size_t len, struct io_buffer *iobuf)
Send data packet via ring buffer.
Definition: vmbus.c:794
struct netvsc_header header
Message header.
Definition: netvsc.h:180
#define ETIMEDOUT
Connection timed out.
Definition: errno.h:669
NetVSC initialisation completion.
Definition: netvsc.h:101
String functions.
struct netvsc_buffer rx
Receive buffer.
Definition: netvsc.h:357
int netdev_open(struct net_device *netdev)
Open network device.
Definition: netdevice.c:861
int wait_rc
Return status code for current blocking transaction.
Definition: netvsc.h:362
#define NETVSC_RNDIS_CONTROL
RNDIS control channel (for all other RNDIS messages)
Definition: netvsc.h:230
static int netvsc_recv_data(struct vmbus_device *vmdev, uint64_t xid, const void *data, size_t len, struct list_head *list)
Handle received data packet.
Definition: netvsc.c:318
static int netvsc_create_buffer(struct netvsc_device *netvsc, struct netvsc_buffer *buffer)
Create data buffer.
Definition: netvsc.c:643
uint8_t * ids
Buffer ID ring.
Definition: netvsc.h:242
void * memset(void *dest, int character, size_t len) __nonnull
A persistent I/O buffer.
Definition: iobuf.h:37