From df59ff37299c921a10aa75988b9d49cc3084cde6 Mon Sep 17 00:00:00 2001
From: Mohammad Javad Pooladkhay <m.pooladkhay@gmail.com>
Date: Sat, 25 Nov 2023 01:17:27 +0000
Subject: [PATCH] integration-test: add tc_name_limit_exceeded test and add
 more useful comments

Signed-off-by: Mohammad Javad Pooladkhay <m.pooladkhay@gmail.com>
---
 test/integration-test/src/tests/load.rs | 59 ++++++++++++++++++++++---
 1 file changed, 54 insertions(+), 5 deletions(-)

diff --git a/test/integration-test/src/tests/load.rs b/test/integration-test/src/tests/load.rs
index 7187ac78..7f66a4f3 100644
--- a/test/integration-test/src/tests/load.rs
+++ b/test/integration-test/src/tests/load.rs
@@ -12,7 +12,8 @@ use aya::{
         links::{FdLink, PinnedLink},
         loaded_links, loaded_programs,
         tc::{clsact_qdisc_exists, qdisc_add_clsact},
-        KProbe, SchedClassifier, TcAttachType, TracePoint, UProbe, Xdp, XdpFlags,
+        KProbe, ProgramError, SchedClassifier, TcAttachType, TcError, TracePoint, UProbe, Xdp,
+        XdpFlags,
     },
     util::KernelVersion,
     Bpf,
@@ -32,10 +33,15 @@ fn tc_name_limit() {
 
     let mut bpf = Bpf::load(crate::TC_NAME_LIMIT_TEST).unwrap();
 
-    // This magic number (256) is derived from the fact that the kernel
-    // permits names with a maximum length of 256 bytes:
-    // https://github.com/torvalds/linux/blob/02aee814/net/sched/cls_bpf.c#L28
-    // In this case, the name is 256 'a's
+    /*
+    A 256-byte-long name (all 'a's) to be used as the name of the
+    ebpf program. This name must match the name passed to the kernel
+    side (i.e. test/integration-ebpf/src/tc_name_limit.rs).
+
+    256 is the maximum length allowed by the kernel, so this test
+    should pass.
+    https://github.com/torvalds/linux/blob/02aee814/net/sched/cls_bpf.c#L28
+    */
     let long_name = "a".repeat(256);
 
     let program: &mut SchedClassifier = bpf
@@ -47,6 +53,49 @@ fn tc_name_limit() {
     program.attach("lo", TcAttachType::Ingress).unwrap();
 }
 
+#[test]
+fn tc_name_limit_exceeded() {
+    let clsact_exists = clsact_qdisc_exists("lo").unwrap();
+    if !clsact_exists {
+        qdisc_add_clsact("lo").unwrap();
+    }
+
+    let mut bpf = Bpf::load(crate::TC_NAME_LIMIT_EXCEEDED_TEST).unwrap();
+
+    /*
+    A 257-byte-long name (all 'a's) to be used as the name of the
+    ebpf program. This name must match the name passed to the kernel
+    side (i.e. test/integration-ebpf/src/tc_name_limit_exceeded.rs).
+
+    256 is the maximum length allowed by the kernel, so this test
+    should fail.
+    https://github.com/torvalds/linux/blob/02aee814/net/sched/cls_bpf.c#L28
+    */
+    let long_name = "a".repeat(257);
+
+    let program: &mut SchedClassifier = bpf
+        .program_mut(long_name.as_str())
+        .unwrap()
+        .try_into()
+        .unwrap();
+    program.load().unwrap();
+
+    // This code should fail while trying to attach the eBPF program
+    // with a name longer that the maximum length allowed by the kernel,
+    // as a result, all arms except the desired Err() should be unreachable!().
+    match program.attach("lo", TcAttachType::Ingress) {
+        Ok(_) => unreachable!(),
+        Err(ProgramError::TcError(TcError::NetlinkError { io_error })) => {
+            // This assertion is checking that the raw OS error code associated
+            // with the io_error is indeed 22, indicating that an invalid argument
+            // error (EINVAL) occurred. In this case, the invalid argument is
+            // the tc program name which is too long.
+            assert_eq!(io_error.raw_os_error(), Some(22));
+        }
+        _ => unreachable!(),
+    }
+}
+
 #[test]
 fn long_name() {
     let mut bpf = Bpf::load(crate::NAME_TEST).unwrap();