class_test.go 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. package netlink
  2. import (
  3. "testing"
  4. )
  5. func TestClassAddDel(t *testing.T) {
  6. tearDown := setUpNetlinkTest(t)
  7. defer tearDown()
  8. if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
  9. t.Fatal(err)
  10. }
  11. if err := LinkAdd(&Ifb{LinkAttrs{Name: "bar"}}); err != nil {
  12. t.Fatal(err)
  13. }
  14. link, err := LinkByName("foo")
  15. if err != nil {
  16. t.Fatal(err)
  17. }
  18. if err := LinkSetUp(link); err != nil {
  19. t.Fatal(err)
  20. }
  21. attrs := QdiscAttrs{
  22. LinkIndex: link.Attrs().Index,
  23. Handle: MakeHandle(0xffff, 0),
  24. Parent: HANDLE_ROOT,
  25. }
  26. qdisc := NewHtb(attrs)
  27. if err := QdiscAdd(qdisc); err != nil {
  28. t.Fatal(err)
  29. }
  30. qdiscs, err := QdiscList(link)
  31. if err != nil {
  32. t.Fatal(err)
  33. }
  34. if len(qdiscs) != 1 {
  35. t.Fatal("Failed to add qdisc")
  36. }
  37. _, ok := qdiscs[0].(*Htb)
  38. if !ok {
  39. t.Fatal("Qdisc is the wrong type")
  40. }
  41. classattrs := ClassAttrs{
  42. LinkIndex: link.Attrs().Index,
  43. Parent: MakeHandle(0xffff, 0),
  44. Handle: MakeHandle(0xffff, 2),
  45. }
  46. htbclassattrs := HtbClassAttrs{
  47. Rate: 1234000,
  48. Cbuffer: 1690,
  49. }
  50. class := NewHtbClass(classattrs, htbclassattrs)
  51. if err := ClassAdd(class); err != nil {
  52. t.Fatal(err)
  53. }
  54. classes, err := ClassList(link, MakeHandle(0xffff, 0))
  55. if err != nil {
  56. t.Fatal(err)
  57. }
  58. if len(classes) != 1 {
  59. t.Fatal("Failed to add class")
  60. }
  61. htb, ok := classes[0].(*HtbClass)
  62. if !ok {
  63. t.Fatal("Class is the wrong type")
  64. }
  65. if htb.Rate != class.Rate {
  66. t.Fatal("Rate doesn't match")
  67. }
  68. if htb.Ceil != class.Ceil {
  69. t.Fatal("Ceil doesn't match")
  70. }
  71. if htb.Buffer != class.Buffer {
  72. t.Fatal("Buffer doesn't match")
  73. }
  74. if htb.Cbuffer != class.Cbuffer {
  75. t.Fatal("Cbuffer doesn't match")
  76. }
  77. qattrs := QdiscAttrs{
  78. LinkIndex: link.Attrs().Index,
  79. Handle: MakeHandle(0x2, 0),
  80. Parent: MakeHandle(0xffff, 2),
  81. }
  82. nattrs := NetemQdiscAttrs{
  83. Latency: 20000,
  84. Loss: 23.4,
  85. Duplicate: 14.3,
  86. LossCorr: 8.34,
  87. Jitter: 1000,
  88. DelayCorr: 12.3,
  89. ReorderProb: 23.4,
  90. CorruptProb: 10.0,
  91. CorruptCorr: 10,
  92. }
  93. qdiscnetem := NewNetem(qattrs, nattrs)
  94. if err := QdiscAdd(qdiscnetem); err != nil {
  95. t.Fatal(err)
  96. }
  97. qdiscs, err = QdiscList(link)
  98. if err != nil {
  99. t.Fatal(err)
  100. }
  101. if len(qdiscs) != 2 {
  102. t.Fatal("Failed to add qdisc")
  103. }
  104. _, ok = qdiscs[0].(*Htb)
  105. if !ok {
  106. t.Fatal("Qdisc is the wrong type")
  107. }
  108. netem, ok := qdiscs[1].(*Netem)
  109. if !ok {
  110. t.Fatal("Qdisc is the wrong type")
  111. }
  112. // Compare the record we got from the list with the one we created
  113. if netem.Loss != qdiscnetem.Loss {
  114. t.Fatal("Loss does not match")
  115. }
  116. if netem.Latency != qdiscnetem.Latency {
  117. t.Fatal("Latency does not match")
  118. }
  119. if netem.CorruptProb != qdiscnetem.CorruptProb {
  120. t.Fatal("CorruptProb does not match")
  121. }
  122. if netem.Jitter != qdiscnetem.Jitter {
  123. t.Fatal("Jitter does not match")
  124. }
  125. if netem.LossCorr != qdiscnetem.LossCorr {
  126. t.Fatal("Loss does not match")
  127. }
  128. if netem.DuplicateCorr != qdiscnetem.DuplicateCorr {
  129. t.Fatal("DuplicateCorr does not match")
  130. }
  131. // Deletion
  132. if err := ClassDel(class); err != nil {
  133. t.Fatal(err)
  134. }
  135. classes, err = ClassList(link, MakeHandle(0xffff, 0))
  136. if err != nil {
  137. t.Fatal(err)
  138. }
  139. if len(classes) != 0 {
  140. t.Fatal("Failed to remove class")
  141. }
  142. if err := QdiscDel(qdisc); err != nil {
  143. t.Fatal(err)
  144. }
  145. qdiscs, err = QdiscList(link)
  146. if err != nil {
  147. t.Fatal(err)
  148. }
  149. if len(qdiscs) != 0 {
  150. t.Fatal("Failed to remove qdisc")
  151. }
  152. }
  153. func TestHtbClassAddHtbClassChangeDel(t *testing.T) {
  154. /**
  155. This test first set up a interface ans set up a Htb qdisc
  156. A HTB class is attach to it and a Netem qdisc is attached to that class
  157. Next, we test changing the HTB class in place and confirming the Netem is
  158. still attached. We also check that invoting ClassChange with a non-existing
  159. class will fail.
  160. Finally, we test ClassReplace. We confirm it correctly behave like
  161. ClassChange when the parent/handle pair exists and that it will create a
  162. new class if the handle is modified.
  163. */
  164. tearDown := setUpNetlinkTest(t)
  165. defer tearDown()
  166. if err := LinkAdd(&Ifb{LinkAttrs{Name: "foo"}}); err != nil {
  167. t.Fatal(err)
  168. }
  169. link, err := LinkByName("foo")
  170. if err != nil {
  171. t.Fatal(err)
  172. }
  173. if err := LinkSetUp(link); err != nil {
  174. t.Fatal(err)
  175. }
  176. attrs := QdiscAttrs{
  177. LinkIndex: link.Attrs().Index,
  178. Handle: MakeHandle(0xffff, 0),
  179. Parent: HANDLE_ROOT,
  180. }
  181. qdisc := NewHtb(attrs)
  182. if err := QdiscAdd(qdisc); err != nil {
  183. t.Fatal(err)
  184. }
  185. qdiscs, err := QdiscList(link)
  186. if err != nil {
  187. t.Fatal(err)
  188. }
  189. if len(qdiscs) != 1 {
  190. t.Fatal("Failed to add qdisc")
  191. }
  192. _, ok := qdiscs[0].(*Htb)
  193. if !ok {
  194. t.Fatal("Qdisc is the wrong type")
  195. }
  196. classattrs := ClassAttrs{
  197. LinkIndex: link.Attrs().Index,
  198. Parent: MakeHandle(0xffff, 0),
  199. Handle: MakeHandle(0xffff, 2),
  200. }
  201. htbclassattrs := HtbClassAttrs{
  202. Rate: 1234000,
  203. Cbuffer: 1690,
  204. }
  205. class := NewHtbClass(classattrs, htbclassattrs)
  206. if err := ClassAdd(class); err != nil {
  207. t.Fatal(err)
  208. }
  209. classes, err := ClassList(link, 0)
  210. if err != nil {
  211. t.Fatal(err)
  212. }
  213. if len(classes) != 1 {
  214. t.Fatal("Failed to add class")
  215. }
  216. htb, ok := classes[0].(*HtbClass)
  217. if !ok {
  218. t.Fatal("Class is the wrong type")
  219. }
  220. qattrs := QdiscAttrs{
  221. LinkIndex: link.Attrs().Index,
  222. Handle: MakeHandle(0x2, 0),
  223. Parent: MakeHandle(0xffff, 2),
  224. }
  225. nattrs := NetemQdiscAttrs{
  226. Latency: 20000,
  227. Loss: 23.4,
  228. Duplicate: 14.3,
  229. LossCorr: 8.34,
  230. Jitter: 1000,
  231. DelayCorr: 12.3,
  232. ReorderProb: 23.4,
  233. CorruptProb: 10.0,
  234. CorruptCorr: 10,
  235. }
  236. qdiscnetem := NewNetem(qattrs, nattrs)
  237. if err := QdiscAdd(qdiscnetem); err != nil {
  238. t.Fatal(err)
  239. }
  240. qdiscs, err = QdiscList(link)
  241. if err != nil {
  242. t.Fatal(err)
  243. }
  244. if len(qdiscs) != 2 {
  245. t.Fatal("Failed to add qdisc")
  246. }
  247. _, ok = qdiscs[1].(*Netem)
  248. if !ok {
  249. t.Fatal("Qdisc is the wrong type")
  250. }
  251. // Change
  252. // For change to work, the handle and parent cannot be changed.
  253. // First, test it fails if we change the Handle.
  254. oldHandle := classattrs.Handle
  255. classattrs.Handle = MakeHandle(0xffff, 3)
  256. class = NewHtbClass(classattrs, htbclassattrs)
  257. if err := ClassChange(class); err == nil {
  258. t.Fatal("ClassChange should not work when using a different handle.")
  259. }
  260. // It should work with the same handle
  261. classattrs.Handle = oldHandle
  262. htbclassattrs.Rate = 4321000
  263. class = NewHtbClass(classattrs, htbclassattrs)
  264. if err := ClassChange(class); err != nil {
  265. t.Fatal(err)
  266. }
  267. classes, err = ClassList(link, MakeHandle(0xffff, 0))
  268. if err != nil {
  269. t.Fatal(err)
  270. }
  271. if len(classes) != 1 {
  272. t.Fatalf(
  273. "1 class expected, %d found",
  274. len(classes),
  275. )
  276. }
  277. htb, ok = classes[0].(*HtbClass)
  278. if !ok {
  279. t.Fatal("Class is the wrong type")
  280. }
  281. // Verify that the rate value has changed.
  282. if htb.Rate != class.Rate {
  283. t.Fatal("Rate did not get changed while changing the class.")
  284. }
  285. // Check that we still have the netem child qdisc
  286. qdiscs, err = QdiscList(link)
  287. if err != nil {
  288. t.Fatal(err)
  289. }
  290. if len(qdiscs) != 2 {
  291. t.Fatalf("2 qdisc expected, %d found", len(qdiscs))
  292. }
  293. _, ok = qdiscs[0].(*Htb)
  294. if !ok {
  295. t.Fatal("Qdisc is the wrong type")
  296. }
  297. _, ok = qdiscs[1].(*Netem)
  298. if !ok {
  299. t.Fatal("Qdisc is the wrong type")
  300. }
  301. // Replace
  302. // First replace by keeping the same handle, class will be changed.
  303. // Then, replace by providing a new handle, n new class will be created.
  304. // Replace acting as Change
  305. class = NewHtbClass(classattrs, htbclassattrs)
  306. if err := ClassReplace(class); err != nil {
  307. t.Fatal("Failed to replace class that is existing.")
  308. }
  309. classes, err = ClassList(link, MakeHandle(0xffff, 0))
  310. if err != nil {
  311. t.Fatal(err)
  312. }
  313. if len(classes) != 1 {
  314. t.Fatalf(
  315. "1 class expected, %d found",
  316. len(classes),
  317. )
  318. }
  319. htb, ok = classes[0].(*HtbClass)
  320. if !ok {
  321. t.Fatal("Class is the wrong type")
  322. }
  323. // Verify that the rate value has changed.
  324. if htb.Rate != class.Rate {
  325. t.Fatal("Rate did not get changed while changing the class.")
  326. }
  327. // It should work with the same handle
  328. classattrs.Handle = MakeHandle(0xffff, 3)
  329. class = NewHtbClass(classattrs, htbclassattrs)
  330. if err := ClassReplace(class); err != nil {
  331. t.Fatal(err)
  332. }
  333. classes, err = ClassList(link, MakeHandle(0xffff, 0))
  334. if err != nil {
  335. t.Fatal(err)
  336. }
  337. if len(classes) != 2 {
  338. t.Fatalf(
  339. "2 classes expected, %d found",
  340. len(classes),
  341. )
  342. }
  343. htb, ok = classes[1].(*HtbClass)
  344. if !ok {
  345. t.Fatal("Class is the wrong type")
  346. }
  347. // Verify that the rate value has changed.
  348. if htb.Rate != class.Rate {
  349. t.Fatal("Rate did not get changed while changing the class.")
  350. }
  351. // Deletion
  352. for _, class := range classes {
  353. if err := ClassDel(class); err != nil {
  354. t.Fatal(err)
  355. }
  356. }
  357. classes, err = ClassList(link, MakeHandle(0xffff, 0))
  358. if err != nil {
  359. t.Fatal(err)
  360. }
  361. if len(classes) != 0 {
  362. t.Fatal("Failed to remove class")
  363. }
  364. if err := QdiscDel(qdisc); err != nil {
  365. t.Fatal(err)
  366. }
  367. qdiscs, err = QdiscList(link)
  368. if err != nil {
  369. t.Fatal(err)
  370. }
  371. if len(qdiscs) != 0 {
  372. t.Fatal("Failed to remove qdisc")
  373. }
  374. }