Skip to content

Commit

Permalink
Merge pull request #18 from uni-tue-kn/dev
Browse files Browse the repository at this point in the history
Merge bugfixes from dev
  • Loading branch information
NE4Y authored Mar 19, 2024
2 parents 4e98650 + 7bce638 commit c1b824e
Show file tree
Hide file tree
Showing 26 changed files with 319 additions and 49 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## v2.2.1
- Better support for 4-pipe Tofino
- Increase meter entries & register entries to 512 to be able to use ports with PID > 255
- Bug in analyze mode that returned an error when no streams / stream settings were provided
- Preliminary import/export function for settings
- Fix bug that prevents that ARP replies are always generated in ANALYZE mode

## v2.2.0
- Added VxLAN support
- Added infobox in UI to get further information on features
Expand Down
15 changes: 7 additions & 8 deletions Configuration GUI/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@ import Settings from "./sites/Settings";
import Offline from "./sites/Offline"
import Tables from "./sites/Tables";
import config from "./config";
import {DefaultStream, DefaultStreamSettings, StreamSettings} from "./common/Interfaces";
import {StreamSettings} from "./common/Interfaces";
import {Stream} from "./common/Interfaces";
import {validateStreams, validateStreamSettings} from "./common/Validators";


const App = () => {
const [error, set_error] = useState(false)
Expand All @@ -55,28 +57,25 @@ const App = () => {
`



// Validates the stored streams and stream settings in the local storage
// Clears local storage if some streams/settings are not valid
// This may be needed if the UI got an update (new stream properties), but the local storage
// holds "old" streams/settings without the new property
const validateLocalStorage = () => {
const defaultStream = DefaultStream(1)
const defaultStreamSetting = DefaultStreamSettings(1, 5)

try {
let stored_streams: Stream[] = JSON.parse(localStorage.getItem("streams") ?? "[]")
let stored_settings: StreamSettings[] = JSON.parse(localStorage.getItem("streamSettings") ?? "[]")

if(!stored_streams.every(s => Object.keys(defaultStream).every(key => Object.keys(s).includes(key)))) {
if(!validateStreams(stored_streams)) {
alert("Incompatible stream description found. This may be due to an update. Resetting local storage.")
localStorage.clear()
window.location.reload()
return
}

if(!stored_settings.every(s => Object.keys(defaultStreamSetting).every(key => {
return Object.keys(s).includes(key) && s.mpls_stack != undefined
}))) {
if(!validateStreamSettings(stored_settings)) {
alert("Incompatible stream description found. This may be due to an update. Resetting local storage.")
localStorage.clear()
window.location.reload()
Expand Down
7 changes: 7 additions & 0 deletions Configuration GUI/src/common/Interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,10 @@ export interface P4TGConfig {
arp_reply: boolean
}[]
}

export interface TrafficGenData {
mode: GenerationMode,
streams: Stream[],
stream_settings: StreamSettings[],
port_tx_rx_mapping: { [name: number]: number}[]
}
23 changes: 22 additions & 1 deletion Configuration GUI/src/common/Validators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* Steffen Lindner (steffen.lindner@uni-tuebingen.de)
*/

import {MPLSHeader} from "./Interfaces";
import {DefaultStream, DefaultStreamSettings, MPLSHeader, Stream, StreamSettings} from "./Interfaces";

export const validateMAC = (mac: string) => {
let regex = /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/;
Expand Down Expand Up @@ -49,4 +49,25 @@ export const validateUdpPort = (port: number) => {

export const validateVNI = (vni: number) => {
return !isNaN(vni) && (0 <= vni) && vni <= (2 ** 24 - 1)
}

export const validateStreams = (s: Stream[]) => {
const defaultStream = DefaultStream(1)

return s.every(s => Object.keys(defaultStream).every(key => Object.keys(s).includes(key)))
}

export const validateStreamSettings = (s: StreamSettings[]) => {
const defaultStreamSetting = DefaultStreamSettings(1, 5)
return s.every(s => Object.keys(defaultStreamSetting).every(key => {
return Object.keys(s).includes(key) && s.mpls_stack != undefined && Object.keys(defaultStreamSetting.vlan).every(key => {
return Object.keys(s.vlan).includes(key)
}) && Object.keys(defaultStreamSetting.ethernet).every(key => { // ethernet
return Object.keys(s.ethernet).includes(key)
}) && Object.keys(defaultStreamSetting.ip).every(key => { // ip
return Object.keys(s.ip).includes(key)
}) && Object.keys(defaultStreamSetting.vxlan).every(key => {
return Object.keys(s.vxlan).includes(key) // VxLAN
})
}))
}
2 changes: 1 addition & 1 deletion Configuration GUI/src/components/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ const Navbar = () => {
</Row>
<Row>
<CNavItem className="flex-grow-1 mb-2">
<span>v2.2.0</span>
<span>v2.2.1</span>
</CNavItem>
</Row>
</CSidebarNav>
Expand Down
99 changes: 91 additions & 8 deletions Configuration GUI/src/sites/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* Steffen Lindner (steffen.lindner@uni-tuebingen.de)
*/

import React, {useEffect, useState} from 'react'
import React, {useEffect, useRef, useState} from 'react'
import {Button, Col, Form, Row, Table} from "react-bootstrap";
import {get} from "../common/API";
import Loader from "../components/Loader";
Expand All @@ -26,14 +26,15 @@ import {
DefaultStreamSettings,
GenerationMode,
Stream,
StreamSettings,
StreamSettings, TrafficGenData,
} from "../common/Interfaces";
import styled from "styled-components";
import InfoBox from "../components/InfoBox";

import {GitHub} from "./Home";
import StreamSettingsList from "../components/settings/StreamSettingsList";
import StreamElement from "../components/settings/StreamElement";
import {validateStreams, validateStreamSettings} from "../common/Validators";

export const StyledRow = styled.tr`
display: flex;
Expand Down Expand Up @@ -66,6 +67,7 @@ const Settings = () => {

const [mode, set_mode] = useState(parseInt(localStorage.getItem("gen-mode") || String(GenerationMode.NONE)))
const [loaded, set_loaded] = useState(false)
const ref = useRef()

const loadPorts = async () => {
let stats = await get({route: "/ports"})
Expand Down Expand Up @@ -163,6 +165,61 @@ const Settings = () => {
set_stream_settings(stream_settings.filter(v => v.stream_id != id))
}

const exportSettings = () => {
const settings = {
"mode": mode,
"stream_settings": stream_settings,
"streams": streams,
"port_tx_rx_mapping": port_tx_rx_mapping
}

const json = `data:text/json;charset=utf-8,${encodeURIComponent(
JSON.stringify(settings, null, "\t")
)}`

const link = document.createElement("a");
link.href = json
link.download = "settings.json"

link.click()
}

const importSettings = (e: any) => {
// @ts-ignore
ref.current.click()
}

const loadSettings = (e: any) => {
e.preventDefault()

const fileReader = new FileReader();
fileReader.readAsText(e.target.files[0], "UTF-8");

fileReader.onload = (e: any) => {
let data: TrafficGenData = JSON.parse(e.target.result)

if(!validateStreams(data.streams) || !validateStreamSettings(data.stream_settings)) {
alert("Settings not valid.")
// @ts-ignore
ref.current.value = ""
}
else {
localStorage.setItem("streams", JSON.stringify(data.streams))
localStorage.setItem("gen-mode", String(data.mode))

localStorage.setItem("streamSettings", JSON.stringify(data.stream_settings))

localStorage.setItem("port_tx_rx_mapping", JSON.stringify(data.port_tx_rx_mapping))

alert("Import successfull. Reloading...")

window.location.reload()
}
}
}

// @ts-ignore
// @ts-ignore
return <Loader loaded={loaded}>
<Row>
<Col className={"col-2"}>
Expand Down Expand Up @@ -193,19 +250,30 @@ const Settings = () => {

<h5>Poisson</h5>

<p>Poisson traffic is traffic with random inter-arrival times but a constant average traffic rate.</p>
<p>Poisson traffic is traffic with random inter-arrival times but a constant average traffic
rate.</p>

<h5>Mpps</h5>

<p>In Mpps mode, P4TG generates traffic with a fixed number of packets per seconds.</p>

<h5>Monitor/Analyze</h5>

<p>In monitor/analyze mode, P4TG forwards traffic received on its ports and measures L1/L2 rates, packet sizes/types and inter-arrival times.</p>
<p>In monitor/analyze mode, P4TG forwards traffic received on its ports and measures L1/L2
rates, packet sizes/types and inter-arrival times.</p>

</>
</InfoBox>
</Col>
<Col className={"text-end"}>
<Button onClick={importSettings} disabled={running} variant={"primary"}>
<i className="bi bi-cloud-arrow-down-fill"/> Import
</Button>
{" "}
<Button onClick={exportSettings} disabled={running} variant={"danger"}>
<i className="bi bi-cloud-arrow-up-fill"/> Export
</Button>
</Col>
</Row>
<Row>

Expand All @@ -222,7 +290,9 @@ const Settings = () => {
<th>Mode</th>
<th>VxLAN &nbsp;
<InfoBox>
<p>VxLAN (<a href={"https://datatracker.ietf.org/doc/html/rfc7348"} target="_blank">RFC 7348</a>) adds an additional outer Ethernet, IP and VxLAN header to the packet.</p>
<p>VxLAN (<a href={"https://datatracker.ietf.org/doc/html/rfc7348"} target="_blank">RFC
7348</a>) adds an additional outer Ethernet, IP and VxLAN header to the packet.
</p>
</InfoBox>
</th>
<th>Encapsulation &nbsp;
Expand Down Expand Up @@ -318,9 +388,22 @@ const Settings = () => {
null
}

<Button onClick={save} disabled={running} variant="primary"><i className="bi bi-check"/> Save</Button>
{" "}
<Button onClick={reset} disabled={running} variant="danger"><i className="bi bi-x-octagon-fill"/> Reset</Button>
<Row>
<Col>
<Button onClick={save} disabled={running} variant="primary"><i className="bi bi-check"/> Save</Button>
{" "}
<Button onClick={reset} disabled={running} variant="danger"><i className="bi bi-x-octagon-fill"/> Reset</Button>
</Col>
</Row>

<input
style={{display: "none"}}
accept=".json"
// @ts-ignore
ref={ref}
onChange={loadSettings}
type="file"
/>

<GitHub/>

Expand Down
2 changes: 1 addition & 1 deletion Controller/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "p4tg-controller"
authors = ["Steffen Lindner <steffen@steffen-lindner.net>"]
version = "0.3.0"
version = "0.3.1"
edition = "2021"
license = "Apache-2.0"

Expand Down
20 changes: 10 additions & 10 deletions Controller/gui_build/asset-manifest.json
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
{
"files": {
"main.css": "/static/css/main.553f51fa.css",
"main.js": "/static/js/main.0356dcbc.js",
"static/js/453.8ab44547.chunk.js": "/static/js/453.8ab44547.chunk.js",
"static/media/bootstrap-icons.woff?": "/static/media/bootstrap-icons.39795c0b4513de014cf8.woff",
"static/media/bootstrap-icons.woff2?": "/static/media/bootstrap-icons.b7bcc075b395c14ce8c2.woff2",
"main.css": "/static/css/main.584e76a8.css",
"main.js": "/static/js/main.78fb8c30.js",
"static/js/787.9e9f4ffd.chunk.js": "/static/js/787.9e9f4ffd.chunk.js",
"static/media/bootstrap-icons.woff?": "/static/media/bootstrap-icons.66b7720f4a230f1b0341.woff",
"static/media/bootstrap-icons.woff2?": "/static/media/bootstrap-icons.64ed46b247405068ca60.woff2",
"static/media/p4tg_logo.png": "/static/media/p4tg_logo.a63d8941e3c0d7219722.png",
"index.html": "/index.html",
"main.553f51fa.css.map": "/static/css/main.553f51fa.css.map",
"main.0356dcbc.js.map": "/static/js/main.0356dcbc.js.map",
"453.8ab44547.chunk.js.map": "/static/js/453.8ab44547.chunk.js.map"
"main.584e76a8.css.map": "/static/css/main.584e76a8.css.map",
"main.78fb8c30.js.map": "/static/js/main.78fb8c30.js.map",
"787.9e9f4ffd.chunk.js.map": "/static/js/787.9e9f4ffd.chunk.js.map"
},
"entrypoints": [
"static/css/main.553f51fa.css",
"static/js/main.0356dcbc.js"
"static/css/main.584e76a8.css",
"static/js/main.78fb8c30.js"
]
}
2 changes: 1 addition & 1 deletion Controller/gui_build/index.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>P4TG</title><script defer="defer" src="/static/js/main.0356dcbc.js"></script><link href="/static/css/main.553f51fa.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>P4TG</title><script defer="defer" src="/static/js/main.78fb8c30.js"></script><link href="/static/css/main.584e76a8.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
3 changes: 3 additions & 0 deletions Controller/gui_build/static/js/main.78fb8c30.js

Large diffs are not rendered by default.

Loading

0 comments on commit c1b824e

Please sign in to comment.