diff --git a/src/hooks/useDrawMiniMap.ts b/src/hooks/useDrawMiniMap.ts index 3496659..3bba297 100644 --- a/src/hooks/useDrawMiniMap.ts +++ b/src/hooks/useDrawMiniMap.ts @@ -134,7 +134,11 @@ export function useDrawMiniMap(chartDom: HTMLElement) { } function drawMinimapTree() { for (const n of Network.Nodes.value) { - if (n.type==NETWORK_TYPE.TSCH && (n).joined && (n).parent != 0) { + if ( + n.type == NETWORK_TYPE.TSCH && + (n).joined && + (n).parent != 0 + ) { if (treeNodes[n.id] == undefined) { treeNodes[n.id] = { name: n.id, children: [] } if (treeNodes[(n).parent] != undefined) { diff --git a/src/networks/5G/network.ts b/src/networks/5G/network.ts index d9b3cc9..d23279a 100644 --- a/src/networks/5G/network.ts +++ b/src/networks/5G/network.ts @@ -1,8 +1,7 @@ import { ref } from 'vue' -import { LINK_TYPE, NETWORK_TYPE, NODE_TYPE } from '../common' +import { Network, LINK_TYPE, NETWORK_TYPE, NODE_TYPE } from '../common' import type { ScheduleConfig, FiveGNodeMeta } from './typedefs' -import { KDNode } from '../kdtree' -import { Network } from '../network' +import { KDNode } from '../../utils/kdtree' export class FiveGNetwork extends Network { constructor() { @@ -25,18 +24,18 @@ export class FiveGNetwork extends Network { } } } - this.Nodes.value = [ - { - id: 0, - type: NODE_TYPE.FIVE_G_BS, - pos: [0, 0], - neighbors: [], - queueLen: 0, - tx_cnt: 0, - rx_cnt: 0, - w: undefined - } - ] + const bs = { + id: 0, + type: NODE_TYPE.FIVE_G_BS, + pos: [0, 0], + neighbors: [], + queueLen: 0, + tx_cnt: 0, + rx_cnt: 0, + w: undefined + } + this.NetworkDevices.value.push(bs) + this.Nodes.value.push(bs) for (let i = 1; i <= this.TopoConfig.value.num_nodes; i++) { const n = { @@ -121,6 +120,7 @@ export class FiveGNetwork extends Network { // } // } this.Nodes.value.push(n) + this.NetworkDevices.value.push(n) } } } diff --git a/src/networks/TSCH/network.ts b/src/networks/TSCH/network.ts index 26bd0e6..12e8017 100644 --- a/src/networks/TSCH/network.ts +++ b/src/networks/TSCH/network.ts @@ -7,10 +7,9 @@ import type { ASSOC_RSP_PKT_PAYLOAD } from './typedefs' import { TSCH_PKT_TYPE, CELL_TYPES } from './typedefs' -import { ADDR, MSG_TYPE, LINK_TYPE, NETWORK_TYPE, NODE_TYPE } from '../common' +import { Network, ADDR, MSG_TYPE, LINK_TYPE, NETWORK_TYPE, NODE_TYPE } from '../common' import type { Packet, Message, ASN_MSG_PAYLOAD, MsgHandler } from '../common' -import { KDNode } from '../kdtree' -import { Network } from '../network' +import { KDNode } from '../../utils/kdtree' export class TSCHNetwork extends Network { doneCnt = 0 @@ -35,7 +34,6 @@ export class TSCHNetwork extends Network { this.registerMsgHandler(MSG_TYPE.ASSOC_REQ, this.assocReqMsgHandler) this.createNodes() - super.createEndSystems() this.createSchedule() watch(this.ASN, () => { @@ -117,8 +115,8 @@ export class TSCHNetwork extends Network { } createNodes = () => { - this.NetworkDevices = ref([]) - + this.NetworkDevices = ref([{}]) + console.log(this.NetworkDevices.value[0].id == undefined) // clear old nodes if (this.NetworkDevices.value.length > 1) { for (const n of this.NetworkDevices.value) { @@ -127,21 +125,6 @@ export class TSCHNetwork extends Network { } } } - this.NetworkDevices.value = [ - { - id: 0, - type: NODE_TYPE.TSCH, - pos: [0, 0], - joined: false, - parent: 0, - neighbors: [], - queueLen: 0, - tx_cnt: 0, - rx_cnt: 0, - rank: 0, - w: undefined - } - ] // placeholder for (let i = 1; i <= this.TopoConfig.value.num_nodes; i++) { const n = { @@ -164,6 +147,9 @@ export class TSCHNetwork extends Network { } this.KDTree.Insert(new KDNode(i, n.pos)) + this.Nodes.value.push(n) + this.NetworkDevices.value.push(n) + // send init msg n.w!.postMessage({ type: MSG_TYPE.INIT, @@ -203,6 +189,7 @@ export class TSCHNetwork extends Network { if (pkt.mac_dst == ADDR.BROADCAST) { for (const nn of this.NetworkDevices.value) { + if (nn.id == undefined) continue // check if in tx_range const distance = Math.sqrt( Math.pow(n.pos[0] - nn.pos[0], 2) + Math.pow(n.pos[1] - nn.pos[1], 2) @@ -226,8 +213,6 @@ export class TSCHNetwork extends Network { } } } - this.Nodes.value.push(n) - this.NetworkDevices.value.push(n) } } diff --git a/src/networks/es.ts b/src/networks/TSN/es.ts similarity index 83% rename from src/networks/es.ts rename to src/networks/TSN/es.ts index a8b358d..5690967 100644 --- a/src/networks/es.ts +++ b/src/networks/TSN/es.ts @@ -1,4 +1,5 @@ -import { MSG_TYPE, type Message, type MsgHandler, type Packet, type PktHandler } from './common' +import { TSN_PKT_TYPE } from './typedefs' +import { MSG_TYPE, type Message, type MsgHandler, type Packet, type PktHandler } from '../common' // end system, run as a webworker class EndSystem { @@ -10,6 +11,9 @@ class EndSystem { constructor() { this.registerMsgHandler(MSG_TYPE.INIT, this.initMsgHandler) + this.registerMsgHandler(MSG_TYPE.FLOW, this.flowMsgHandler) + + this.registerPktHandler(TSN_PKT_TYPE.DATA, this.dataPktHandler) } registerMsgHandler(type: number, handler: MsgHandler) { @@ -46,7 +50,8 @@ class EndSystem { } } initMsgHandler = () => {} - dataMsgHandler = () => {} + flowMsgHandler = () => {} + dataPktHandler = () => {} } new EndSystem().run() diff --git a/src/networks/TSN/network.ts b/src/networks/TSN/network.ts index ce573c5..991f659 100644 --- a/src/networks/TSN/network.ts +++ b/src/networks/TSN/network.ts @@ -1,8 +1,17 @@ import { ref, toRaw } from 'vue' -import { NETWORK_TYPE, NODE_TYPE, type Message, LINK_TYPE, MSG_TYPE } from '../common' +import { + Network, + NETWORK_TYPE, + NODE_TYPE, + type Message, + LINK_TYPE, + MSG_TYPE, + type NodeMeta, + type INIT_MSG_PAYLOAD, + type Packet +} from '../common' import { type ScheduleConfig, type TSNNodeMeta, type TSN_INIT_MSG_PAYLOAD } from './typedefs' -import { KDNode } from '../kdtree' -import { Network } from '../network' +import { KDNode } from '../../utils/kdtree' export class TSNNetwork extends Network { InPorts: any @@ -16,7 +25,7 @@ export class TSNNetwork extends Network { num_slots: 40 }) this.createNodes() - super.createEndSystems() + this.createEndSystems() } createNodes = () => { this.NetworkDevices = ref([]) @@ -84,4 +93,58 @@ export class TSNNetwork extends Network { }) } } + createEndSystems = () => { + // initialize ref array if it does not already exist + this.EndSystems = ref([]) + + for ( + let i = 1 + this.TopoConfig.value.num_nodes; + i <= this.TopoConfig.value.num_es + this.TopoConfig.value.num_nodes; + i++ + ) { + const es = { + id: i, + type: Math.floor(4 + this.Rand.next() * 3), + pos: [ + Math.floor(this.Rand.next() * this.TopoConfig.value.grid_size) - + this.TopoConfig.value.grid_size / 2, + Math.floor(this.Rand.next() * this.TopoConfig.value.grid_size) - + this.TopoConfig.value.grid_size / 2 + ], + tx_cnt: 0, + rx_cnt: 0, + neighbors: [], + w: new Worker(new URL('@/networks/es.ts', import.meta.url), { type: 'module' }) + } + console.log(i) + es.neighbors = this.KDTree.FindKNearest(es.pos, 1, this.TopoConfig.value.grid_size) + if (es.neighbors.length > 0) { + this.addLink(es.id, es.neighbors[0], LINK_TYPE.WIRED) + } + + es.w!.postMessage({ + type: MSG_TYPE.INIT, + payload: { + id: es.id, + pos: toRaw(es.pos) + } + }) + // handle msg/pkt from end systems + es.w!.onmessage = (e: any) => { + if ('uid' in e.data == false) { + const msg: Message = e.data + console.log(msg) + } else { + const pkt: Packet = e.data + this.Nodes.value[pkt.mac_dst].w!.postMessage(pkt) + this.Packets.value.push(pkt) + this.PacketsCurrent.value.push(pkt) + this.SlotDone.value = true + } + } + + this.EndSystems.value.push(es) + this.Nodes.value.push(es) + } + } } diff --git a/src/networks/TSN/typedefs.ts b/src/networks/TSN/typedefs.ts index 62631c9..6758360 100644 --- a/src/networks/TSN/typedefs.ts +++ b/src/networks/TSN/typedefs.ts @@ -11,5 +11,6 @@ export enum TSN_PKT_TYPE { } export interface TSN_INIT_MSG_PAYLOAD extends INIT_MSG_PAYLOAD { + neighbors: number[] sch_config: ScheduleConfig } diff --git a/src/networks/common.ts b/src/networks/common.ts index e202f30..fda9212 100644 --- a/src/networks/common.ts +++ b/src/networks/common.ts @@ -1,3 +1,7 @@ +import { ref, type Ref } from 'vue' +import { SeededRandom } from '@/utils/rand' +import { KDTree } from '@/utils/kdtree' + export enum NETWORK_TYPE { TSCH, TSN, @@ -39,8 +43,11 @@ export enum LINK_TYPE { export interface FlowMeta { id: number - src: number - dst: number + e2e_src: number + e2e_dst: number + deadline: number + period: number + workload: number } // Packet is transfered among nodes, at data-link layer @@ -103,3 +110,76 @@ export interface TopologyConfig { grid_size: number tx_range: number } + +export class Network { + ID: number + Type: number + Nodes = ref([]) // nodes and endsystems, for visualization + NetworkDevices: any // tsn bridges, tsch relay or 5g ue/bs + EndSystems = ref([]) + Links = ref<{ [uid: number]: LinkMeta }>([]) + Flows = ref([]) + TopoConfig: Ref + KDTree: KDTree + SchConfig: any + Schedule: any + Packets = ref([]) + ASN = ref(0) + asnTimer: any + PacketsCurrent = ref([]) + + SignalReset = ref(0) + SlotDone = ref(false) + Running = ref(false) + SlotDuration = ref(750) + + Rand: SeededRandom + + constructor() { + this.ID = 1 + this.Type = -1 + this.TopoConfig = ref({ + seed: 1, + num_nodes: 10, + num_es: 1, + grid_size: 80, + tx_range: 25 + }) + this.Rand = new SeededRandom(this.TopoConfig.value.seed) + this.Nodes.value.push({}) // placeholder + this.KDTree = new KDTree() + } + + addLink(v1: number, v2: number, type: number) { + if (v1 > v2) { + ;[v1, v2] = [v2, v1] + } + // Cantor pairing + const uid = 0.5 * (v1 + v2) * (v1 + v2 + 1) + v2 + if (this.Links.value[uid] == undefined) { + this.Links.value[uid] = { uid, v1, v2, type } + } + } + + Run = () => { + this.Step() + this.Running.value = true + this.asnTimer = setInterval(() => { + this.ASN.value++ + this.SlotDone.value = false + }, this.SlotDuration.value) + } + Step = () => { + this.ASN.value++ + this.SlotDone.value = false + } + Pause = () => { + this.Running.value = false + clearInterval(this.asnTimer) + } + Reset = () => { + this.Running.value = false + clearInterval(this.asnTimer) + this.SignalReset.value++ + } +} diff --git a/src/networks/network.ts b/src/networks/network.ts deleted file mode 100644 index 2950316..0000000 --- a/src/networks/network.ts +++ /dev/null @@ -1,141 +0,0 @@ -import { ref, toRaw, type Ref } from 'vue' -import { SeededRandom } from '@/hooks/useSeed' -import { KDTree } from './kdtree' -import { - LINK_TYPE, - MSG_TYPE, - type LinkMeta, - type Message, - type NodeMeta, - type Packet, - type TopologyConfig, - type INIT_MSG_PAYLOAD, - type FlowMeta -} from './common' - -export class Network { - ID: number - Type: number - Nodes = ref([]) // nodes and endsystems, for visualization - NetworkDevices: any // tsn bridges, tsch relay or 5g ue/bs - EndSystems = ref([]) - Links = ref<{ [uid: number]: LinkMeta }>([]) - Flows = ref([]) - TopoConfig: Ref - KDTree: KDTree - SchConfig: any - Schedule: any - Packets = ref([]) - ASN = ref(0) - asnTimer: any - PacketsCurrent = ref([]) - - SignalReset = ref(0) - SlotDone = ref(false) - Running = ref(false) - SlotDuration = ref(750) - - Rand: SeededRandom - - constructor() { - this.ID = 1 - this.Type = -1 - this.TopoConfig = ref({ - seed: 1, - num_nodes: 10, - num_es: 1, - grid_size: 80, - tx_range: 25 - }) - this.Rand = new SeededRandom(this.TopoConfig.value.seed) - this.Nodes.value.push({}) - this.KDTree = new KDTree() - } - // call after createNodes - createEndSystems() { - // initialize ref array if it does not already exist - this.EndSystems = ref([]) - - for ( - let i = 1 + this.TopoConfig.value.num_nodes; - i <= this.TopoConfig.value.num_es + this.TopoConfig.value.num_nodes; - i++ - ) { - const es = { - id: i, - type: Math.floor(4 + this.Rand.next() * 3), - pos: [ - Math.floor(this.Rand.next() * this.TopoConfig.value.grid_size) - - this.TopoConfig.value.grid_size / 2, - Math.floor(this.Rand.next() * this.TopoConfig.value.grid_size) - - this.TopoConfig.value.grid_size / 2 - ], - tx_cnt: 0, - rx_cnt: 0, - neighbors: [], - w: new Worker(new URL('@/networks/es.ts', import.meta.url), { type: 'module' }) - } - console.log(i) - es.neighbors = this.KDTree.FindKNearest(es.pos, 1, this.TopoConfig.value.grid_size) - if (es.neighbors.length > 0) { - this.addLink(es.id, es.neighbors[0], LINK_TYPE.WIRED) - } - - es.w!.postMessage({ - type: MSG_TYPE.INIT, - payload: { - id: es.id, - pos: toRaw(es.pos) - } - }) - // handle msg/pkt from end systems - es.w!.onmessage = (e: any) => { - if ('uid' in e.data == false) { - const msg: Message = e.data - console.log(msg) - } else { - const pkt: Packet = e.data - this.Nodes.value[pkt.mac_dst].w!.postMessage(pkt) - this.Packets.value.push(pkt) - this.PacketsCurrent.value.push(pkt) - this.SlotDone.value = true - } - } - - this.EndSystems.value.push(es) - this.Nodes.value.push(es) - } - } - addLink(v1: number, v2: number, type: number) { - if (v1 > v2) { - ;[v1, v2] = [v2, v1] - } - // Cantor pairing - const uid = 0.5 * (v1 + v2) * (v1 + v2 + 1) + v2 - if (this.Links.value[uid] == undefined) { - this.Links.value[uid] = { uid, v1, v2, type } - } - } - - Run = () => { - this.Step() - this.Running.value = true - this.asnTimer = setInterval(() => { - this.ASN.value++ - this.SlotDone.value = false - }, this.SlotDuration.value) - } - Step = () => { - this.ASN.value++ - this.SlotDone.value = false - } - Pause = () => { - this.Running.value = false - clearInterval(this.asnTimer) - } - Reset = () => { - this.Running.value = false - clearInterval(this.asnTimer) - this.SignalReset.value++ - } -} diff --git a/src/networks/kdtree.ts b/src/utils/kdtree.ts similarity index 100% rename from src/networks/kdtree.ts rename to src/utils/kdtree.ts diff --git a/src/hooks/useSeed.ts b/src/utils/rand.ts similarity index 95% rename from src/hooks/useSeed.ts rename to src/utils/rand.ts index 09ef2bb..84fe149 100644 --- a/src/hooks/useSeed.ts +++ b/src/utils/rand.ts @@ -1,4 +1,3 @@ -// ai generated code :) export class SeededRandom { private m_w: number private m_z: number