netdevmedium.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "u.h"
  10. #include "../port/lib.h"
  11. #include "mem.h"
  12. #include "dat.h"
  13. #include "fns.h"
  14. #include "../port/error.h"
  15. #include "ip.h"
  16. static void netdevbind(Ipifc *ifc, int argc, char **argv);
  17. static void netdevunbind(Ipifc *ifc);
  18. static void netdevbwrite(Ipifc *ifc, Block *bp, int version, uint8_t *ip);
  19. static void netdevread(void *a);
  20. typedef struct Netdevrock Netdevrock;
  21. struct Netdevrock
  22. {
  23. Fs *f; /* file system we belong to */
  24. Proc *readp; /* reading process */
  25. Chan *mchan; /* Data channel */
  26. };
  27. Medium netdevmedium =
  28. {
  29. .name= "netdev",
  30. .hsize= 0,
  31. .mintu= 0,
  32. .maxtu= 64000,
  33. .maclen= 0,
  34. .bind= netdevbind,
  35. .unbind= netdevunbind,
  36. .bwrite= netdevbwrite,
  37. .unbindonclose= 0,
  38. };
  39. /*
  40. * called to bind an IP ifc to a generic network device
  41. * called with ifc qlock'd
  42. */
  43. static void
  44. netdevbind(Ipifc *ifc, int argc, char **argv)
  45. {
  46. Chan *mchan;
  47. Netdevrock *er;
  48. if(argc < 2)
  49. error(Ebadarg);
  50. mchan = namec(argv[2], Aopen, ORDWR, 0);
  51. er = smalloc(sizeof(*er));
  52. er->mchan = mchan;
  53. er->f = ifc->conv->p->f;
  54. ifc->arg = er;
  55. kproc("netdevread", netdevread, ifc);
  56. }
  57. /*
  58. * called with ifc wlock'd
  59. */
  60. static void
  61. netdevunbind(Ipifc *ifc)
  62. {
  63. Proc *up = externup();
  64. Netdevrock *er = ifc->arg;
  65. if(er->readp != nil)
  66. postnote(er->readp, 1, "unbind", 0);
  67. /* wait for readers to die */
  68. while(er->readp != nil)
  69. tsleep(&up->sleep, return0, 0, 300);
  70. if(er->mchan != nil)
  71. cclose(er->mchan);
  72. free(er);
  73. }
  74. /*
  75. * called by ipoput with a single block to write
  76. */
  77. static void
  78. netdevbwrite(Ipifc *ifc, Block *bp, int i, uint8_t *c)
  79. {
  80. Netdevrock *er = ifc->arg;
  81. if(bp->next)
  82. bp = concatblock(bp);
  83. if(BLEN(bp) < ifc->mintu)
  84. bp = adjustblock(bp, ifc->mintu);
  85. er->mchan->dev->bwrite(er->mchan, bp, 0);
  86. ifc->out++;
  87. }
  88. /*
  89. * process to read from the device
  90. */
  91. static void
  92. netdevread(void *a)
  93. {
  94. Proc *up = externup();
  95. Ipifc *ifc;
  96. Block *bp;
  97. Netdevrock *er;
  98. char *argv[1];
  99. ifc = a;
  100. er = ifc->arg;
  101. er->readp = up; /* hide identity under a rock for unbind */
  102. if(waserror()){
  103. er->readp = nil;
  104. pexit("hangup", 1);
  105. }
  106. for(;;){
  107. bp = er->mchan->dev->bread(er->mchan, ifc->maxtu, 0);
  108. if(bp == nil){
  109. /*
  110. * get here if mchan is a pipe and other side hangs up
  111. * clean up this interface & get out
  112. ZZZ is this a good idea?
  113. */
  114. poperror();
  115. er->readp = nil;
  116. argv[0] = "unbind";
  117. if(!waserror())
  118. ifc->conv->p->ctl(ifc->conv, argv, 1);
  119. pexit("hangup", 1);
  120. }
  121. if(!canrlock(&ifc->rwl)){
  122. freeb(bp);
  123. continue;
  124. }
  125. if(waserror()){
  126. runlock(&ifc->rwl);
  127. nexterror();
  128. }
  129. ifc->in++;
  130. if(ifc->lifc == nil)
  131. freeb(bp);
  132. else
  133. ipiput4(er->f, ifc, bp);
  134. runlock(&ifc->rwl);
  135. poperror();
  136. }
  137. }
  138. void
  139. netdevmediumlink(void)
  140. {
  141. addipmedium(&netdevmedium);
  142. }