From: Gregory Etelson <getelson@nvidia.com>
To: Ferruh Yigit <ferruh.yigit@amd.com>,
Shani Peretz <shperetz@nvidia.com>, "dev@dpdk.org" <dev@dpdk.org>
Cc: Maayan Kashani <mkashani@nvidia.com>, Ori Kam <orika@nvidia.com>,
Aman Singh <aman.deep.singh@intel.com>,
Yuying Zhang <yuying.zhang@intel.com>,
"ci@dpdk.org" <ci@dpdk.org>,
Honnappa Nagarahalli <Honnappa.Nagarahalli@arm.com>,
Patrick Robb <probb@iol.unh.edu>, Asaf Penso <asafp@nvidia.com>
Subject: Re: [PATCH] app/testpmd: fix auto completion for indirect list action
Date: Sat, 23 Mar 2024 10:09:51 +0000 [thread overview]
Message-ID: <DS7PR12MB6336564F8003AA4296B4AACAA5302@DS7PR12MB6336.namprd12.prod.outlook.com> (raw)
In-Reply-To: <46653254-c995-4de0-82fa-2531ed4cfaa0@amd.com>
[-- Attachment #1: Type: text/plain, Size: 5884 bytes --]
Hello Ferruh,
> But I guess it won't catch this issue, as it uses full flow commands.
> This issue is related to the testpmd command parsing code. I wonder if
> we can find a way to verify testpmd parsing code?
What if flow command validation program breaks a tested command into tokens and then pass each token followed by the TAB key to the controlled testpmd process ?
There are 3 possible outputs for the token + TAB sequence:
1. a valid token will trigger meaningful testpmd help ouput that can be matched.
2. invalid token output will fail [1].
3.
invalid token will crash the controlled testpmd process.
I've compiled a small programm to test that idea.
Please check it out.
Regards,
Gregory.
commit e4a27c2c2892cfd408b473b18192b30927e4281c
Author: Gregory Etelson <getelson@nvidia.com>
Date: Sat Mar 23 11:38:44 2024 +0200
validate testpmd flow command
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..3498868
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,12 @@
+[package]
+name = "testpmd-validate"
+version = "0.1.0"
+edition = "2021"
+rust-version = "1.76.0"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+ssh2 = { version = "0.9.4", features = ["vendored-openssl"] }
+time = "0.3.34"
+regex = "1.10.4"
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..90dfdac
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,128 @@
+use std::io::{Read, Write};
+use std::{io, thread, time};
+use std::path::Path;
+use std::ops::Add;
+use std::time::{SystemTime};
+use ssh2::{Channel, Error, ExtendedData, Session};
+use regex::{RegexSet};
+
+fn continue_after_error(err:&io::Error) -> bool {
+ match err.kind() {
+ io::ErrorKind::WouldBlock => return true,
+ _ => return false,
+ }
+}
+
+fn wrap_ssh<F, T>(mut func:F) -> T
+ where F: FnMut() -> Result<T, Error> {
+ loop {
+ match func() {
+ Ok(val) => { return val },
+ Err(ssh_err) => {
+ let io_err = io::Error::from(ssh_err);
+ if !continue_after_error(&io_err) {
+ panic!("ssh2 error: {:?}", io_err);
+ }
+ }
+ }
+ }
+}
+
+fn rsh_write(channel:&mut Channel, buf:&str) {
+ match channel.write(buf.as_bytes()) {
+ Ok(_) => (),
+ Err(e) => panic!("write failure: {:?}", e)
+ }
+}
+
+const RSH_READ_MAX_DURATION:time::Duration = time::Duration::from_millis(350);
+const RSH_READ_IDLE_TIMEOUT:time::Duration = time::Duration::from_millis(10);
+fn rsh_read(channel:&mut Channel) -> String {
+ let mut end = SystemTime::now().add(RSH_READ_MAX_DURATION);
+ let mut output = String::new();
+ loop {
+ let mut buffer: [u8; 1024] = [0; 1024];
+ match channel.read(&mut buffer) {
+ Ok(0) => { return output }
+ Ok(_) => {
+ let aux = String::from_utf8(buffer.into()).unwrap();
+ // println!("{aux}");
+ output.push_str(&aux);
+ end = SystemTime::now().add(RSH_READ_MAX_DURATION);
+ }
+ Err(err) => {
+ if !continue_after_error(&err) { panic!("read error {:?}", err) }
+ if SystemTime::now().gt(&end) { break; }
+ thread::sleep(RSH_READ_IDLE_TIMEOUT);
+ }
+ }
+ }
+ output
+}
+
+const TESTPMD_PATH:&str = "/tmp/build/app";
+const TESTPMD_CMD:&str = "dpdk-testpmd -a 0000:01:00.0 -- -i";
+
+const TOKEN_PATTERN:[&str; 2] = [
+ r#"(?m)\[.*\]:"#,
+ r#"(?m)\[RETURN]"#,
+];
+
+const CTRL_C:[u8;1] = [0x3];
+
+
+fn rsh_connect(hostname:&str) -> Channel {
+ let stream = std::net::TcpStream::connect(format!("{}:22", hostname)).unwrap();
+ stream.set_nonblocking(true).unwrap();
+ let mut session = Session::new().unwrap();
+ let private_key = Path::new("/home/garik/.ssh/id_rsa");
+ session.set_blocking(false);
+ session.set_tcp_stream(stream);
+ wrap_ssh(|| session.handshake());
+ wrap_ssh(|| session.userauth_pubkey_file("root", None, &private_key, None));
+ let mut ch = wrap_ssh(|| session.channel_session());
+ wrap_ssh(|| ch.handle_extended_data(ExtendedData::Merge));
+ wrap_ssh(|| ch.request_pty("vt100", None, None));
+ ch
+}
+
+fn validate_flow_command(command:&str, ch:&mut Channel) {
+ let rset = RegexSet::new(TOKEN_PATTERN).unwrap();
+ let delay = time::Duration::from_millis(300);
+
+ println!("validate: {command}");
+ for token in command.split_whitespace() {
+ let candid = format!("{token} \t");
+ rsh_write(ch, &candid);
+ print!("validate token \'{token}\' ");
+ thread::sleep(delay);
+ let output = rsh_read(ch);
+ if rset.is_match(&output) {
+ println!(" ok");
+ } else {
+ println!("failed");
+ println!(">>>>>>>>>>>>>>>>>>");
+ println!("{output}");
+ println!("<<<<<<<<<<<<<<<<<<");
+ break;
+ }
+ }
+ let _ = ch.write(&CTRL_C);
+}
+
+fn main() {
+ let mut ch = rsh_connect("10.237.157.85");
+ let command = format!("{}/{}", TESTPMD_PATH, TESTPMD_CMD);
+ wrap_ssh(|| ch.exec(&command));
+ thread::sleep(time::Duration::from_secs(1));
+ println!("{}", rsh_read(&mut ch));
+
+ let good_flow = "flow create 0 ingress group 0 priority 0 pattern eth / end actions drop / end";
+ let bad_flow = "flow create 0 ingress group 0 priority 0 pattern eth/ end actions drop / end";
+
+ validate_flow_command(good_flow, &mut ch);
+ validate_flow_command(bad_flow, &mut ch);
+
+ wrap_ssh(|| ch.close());
+ println!("EOF {:?}", ch.exit_status());
+}
[-- Attachment #2: Type: text/html, Size: 39583 bytes --]
prev parent reply other threads:[~2024-03-23 10:09 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20240318092109.87656-1-shperetz@nvidia.com>
[not found] ` <62669854-8add-4fdd-b882-a63d78f0d6e8@amd.com>
2024-03-19 15:29 ` Ferruh Yigit
2024-03-20 6:06 ` Gregory Etelson
2024-03-20 10:08 ` Ferruh Yigit
2024-03-20 20:25 ` Patrick Robb
2024-03-23 10:09 ` Gregory Etelson [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=DS7PR12MB6336564F8003AA4296B4AACAA5302@DS7PR12MB6336.namprd12.prod.outlook.com \
--to=getelson@nvidia.com \
--cc=Honnappa.Nagarahalli@arm.com \
--cc=aman.deep.singh@intel.com \
--cc=asafp@nvidia.com \
--cc=ci@dpdk.org \
--cc=dev@dpdk.org \
--cc=ferruh.yigit@amd.com \
--cc=mkashani@nvidia.com \
--cc=orika@nvidia.com \
--cc=probb@iol.unh.edu \
--cc=shperetz@nvidia.com \
--cc=yuying.zhang@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).