@ndn/dpdkmgmt
Advanced tools
Comparing version 0.0.20210203 to 0.0.20210930
@@ -0,19 +1,26 @@ | ||
import { __importDefault, __importStar } from "tslib"; | ||
import { Forwarder } from "@ndn/fw"; | ||
import { L3Face } from "@ndn/l3face"; | ||
import { UdpTransport } from "@ndn/node-transport"; | ||
import * as dgram from "dgram"; | ||
import { joinHostPort, splitHostPort, udp_helper, UdpTransport } from "@ndn/node-transport"; | ||
import { gql, GraphQLClient } from "graphql-request"; | ||
import * as net from "net"; | ||
import * as path from "path"; | ||
import _cjsDefaultImport0 from "p-event"; const pEvent = __importDefault(_cjsDefaultImport0).default; | ||
import { MemifTransport } from "./memif-transport_browser.js"; | ||
import { NdndpdkPrefixReg } from "./prefix-reg_browser.js"; | ||
/** Open a face on NDN-DPDK. */ | ||
export async function openFace({ fw = Forwarder.getDefault(), attributes = {}, localHost = "127.0.0.1", gqlServer = "http://localhost:3030", } = {}) { | ||
const sock = await new Promise((resolve, reject) => { | ||
const sock = dgram.createSocket({ type: "udp4" }); | ||
sock.on("error", reject); | ||
sock.bind(0, localHost, () => { | ||
sock.off("error", reject); | ||
resolve(sock); | ||
}); | ||
}); | ||
const DefaultGqlServer = "http://127.0.0.1:3030"; | ||
async function detectLocalAddress(gqlServer) { | ||
const { host, port = 80 } = splitHostPort(new URL(gqlServer).host); | ||
if (host === "127.0.0.1") { | ||
return host; | ||
} | ||
const tcpConn = net.connect(port, host); | ||
await pEvent(tcpConn, "connect"); | ||
const { localAddress } = tcpConn; | ||
tcpConn.destroy(); | ||
return localAddress; | ||
} | ||
async function openFaceImpl({ gqlServer = "http://127.0.0.1:3030", fw = Forwarder.getDefault(), attributes = {}, }, locator, prepareTransport) { | ||
const client = new GraphQLClient(gqlServer); | ||
const { createFace: { id, locator: { local: remoteAddr } } } = await client.request(gql ` | ||
const { createFace: { id, locator: loc } } = await client.request(gql ` | ||
mutation createFace($locator: JSON!) { | ||
@@ -26,9 +33,6 @@ createFace(locator: $locator) { | ||
`, { | ||
locator: { | ||
scheme: "udp", | ||
remote: `${localHost}:${sock.address().port}`, | ||
}, | ||
locator, | ||
}); | ||
const prefixReg = new NdndpdkPrefixReg(client, id); | ||
sock.on("close", async () => { | ||
const cleanup = async () => { | ||
prefixReg.disable(); | ||
@@ -42,26 +46,82 @@ await client.request(gql ` | ||
}); | ||
}); | ||
await new Promise((resolve, reject) => { | ||
const [remoteHost, remotePort] = remoteAddr.split(":"); | ||
const handleError = () => { | ||
sock.close(); | ||
reject(); | ||
}; | ||
if (!remoteHost || !remotePort) { | ||
handleError(); | ||
return; | ||
} | ||
sock.once("error", handleError); | ||
sock.connect(Number.parseInt(remotePort, 10), remoteHost, () => { | ||
sock.off("error", handleError); | ||
resolve(); | ||
}); | ||
}); | ||
const transport = new UdpTransport(sock); | ||
}; | ||
let transport; | ||
let mtu; | ||
try { | ||
[transport, mtu] = await prepareTransport(loc); | ||
} | ||
catch (err) { | ||
await cleanup(); | ||
throw err; | ||
} | ||
prefixReg.enable(fw); | ||
return fw.addFace(new L3Face(transport, { | ||
const face = fw.addFace(new L3Face(transport, { | ||
advertiseFrom: false, | ||
describe: `NDN-DPDK(${id})`, | ||
...attributes, | ||
}, { | ||
mtu, | ||
})); | ||
face.on("close", cleanup); | ||
return face; | ||
} | ||
async function openFaceUdp(opts) { | ||
let { gqlServer = DefaultGqlServer, localHost, udp: udpOptionsInput, } = opts; | ||
localHost ?? (localHost = await detectLocalAddress(gqlServer)); | ||
const sock = await udp_helper.openSocket({ | ||
bind: { address: localHost }, | ||
...udpOptionsInput, | ||
}); | ||
try { | ||
return await openFaceImpl(opts, { | ||
scheme: "udp", | ||
remote: joinHostPort(localHost, sock.address().port), | ||
}, async (loc) => { | ||
const { host, port } = splitHostPort(loc.local ?? ""); | ||
if (!host || !port) { | ||
throw new Error(`unexpected locator: ${JSON.stringify(loc)}`); | ||
} | ||
await udp_helper.connect(sock, { host, port }); | ||
return [new UdpTransport(sock), 1450]; | ||
}); | ||
} | ||
catch (err) { | ||
sock.close(); | ||
throw err; | ||
} | ||
} | ||
async function openFaceMemif(opts) { | ||
const { memif: memifOptionsInput = {}, } = opts; | ||
const { socketPath = "/run/ndn", dataroom = 2048, ringCapacity = 1024, } = memifOptionsInput; | ||
const socketName = path.join(socketPath, `NDNts-memif-${process.pid}-${Date.now()}.sock`); | ||
return openFaceImpl(opts, { | ||
scheme: "memif", | ||
role: "server", | ||
socketName, | ||
socketOwner: [process.getuid(), process.getgid()], | ||
id: 0, | ||
dataroom, | ||
ringCapacity, | ||
}, async () => { | ||
const transport = await MemifTransport.connect({ | ||
role: "client", | ||
socketName, | ||
id: 0, | ||
dataroom, | ||
ringCapacity, | ||
}); | ||
return [transport, dataroom]; | ||
}); | ||
} | ||
/** Open a face on NDN-DPDK. */ | ||
export async function openFace(opts = {}) { | ||
const { scheme = "udp", } = opts; | ||
switch (scheme) { | ||
case "udp": | ||
return openFaceUdp(opts); | ||
case "memif": | ||
return openFaceMemif(opts); | ||
default: | ||
throw new Error(`unknown scheme ${scheme}`); | ||
} | ||
} |
@@ -0,19 +1,26 @@ | ||
import { __importDefault, __importStar } from "tslib"; | ||
import { Forwarder } from "@ndn/fw"; | ||
import { L3Face } from "@ndn/l3face"; | ||
import { UdpTransport } from "@ndn/node-transport"; | ||
import * as dgram from "dgram"; | ||
import { joinHostPort, splitHostPort, udp_helper, UdpTransport } from "@ndn/node-transport"; | ||
import { gql, GraphQLClient } from "graphql-request"; | ||
import * as net from "node:net"; | ||
import * as path from "node:path"; | ||
import _cjsDefaultImport0 from "p-event"; const pEvent = __importDefault(_cjsDefaultImport0).default; | ||
import { MemifTransport } from "./memif-transport_node.js"; | ||
import { NdndpdkPrefixReg } from "./prefix-reg_node.js"; | ||
/** Open a face on NDN-DPDK. */ | ||
export async function openFace({ fw = Forwarder.getDefault(), attributes = {}, localHost = "127.0.0.1", gqlServer = "http://localhost:3030", } = {}) { | ||
const sock = await new Promise((resolve, reject) => { | ||
const sock = dgram.createSocket({ type: "udp4" }); | ||
sock.on("error", reject); | ||
sock.bind(0, localHost, () => { | ||
sock.off("error", reject); | ||
resolve(sock); | ||
}); | ||
}); | ||
const DefaultGqlServer = "http://127.0.0.1:3030"; | ||
async function detectLocalAddress(gqlServer) { | ||
const { host, port = 80 } = splitHostPort(new URL(gqlServer).host); | ||
if (host === "127.0.0.1") { | ||
return host; | ||
} | ||
const tcpConn = net.connect(port, host); | ||
await pEvent(tcpConn, "connect"); | ||
const { localAddress } = tcpConn; | ||
tcpConn.destroy(); | ||
return localAddress; | ||
} | ||
async function openFaceImpl({ gqlServer = "http://127.0.0.1:3030", fw = Forwarder.getDefault(), attributes = {}, }, locator, prepareTransport) { | ||
const client = new GraphQLClient(gqlServer); | ||
const { createFace: { id, locator: { local: remoteAddr } } } = await client.request(gql ` | ||
const { createFace: { id, locator: loc } } = await client.request(gql ` | ||
mutation createFace($locator: JSON!) { | ||
@@ -26,9 +33,6 @@ createFace(locator: $locator) { | ||
`, { | ||
locator: { | ||
scheme: "udp", | ||
remote: `${localHost}:${sock.address().port}`, | ||
}, | ||
locator, | ||
}); | ||
const prefixReg = new NdndpdkPrefixReg(client, id); | ||
sock.on("close", async () => { | ||
const cleanup = async () => { | ||
prefixReg.disable(); | ||
@@ -42,26 +46,82 @@ await client.request(gql ` | ||
}); | ||
}); | ||
await new Promise((resolve, reject) => { | ||
const [remoteHost, remotePort] = remoteAddr.split(":"); | ||
const handleError = () => { | ||
sock.close(); | ||
reject(); | ||
}; | ||
if (!remoteHost || !remotePort) { | ||
handleError(); | ||
return; | ||
} | ||
sock.once("error", handleError); | ||
sock.connect(Number.parseInt(remotePort, 10), remoteHost, () => { | ||
sock.off("error", handleError); | ||
resolve(); | ||
}); | ||
}); | ||
const transport = new UdpTransport(sock); | ||
}; | ||
let transport; | ||
let mtu; | ||
try { | ||
[transport, mtu] = await prepareTransport(loc); | ||
} | ||
catch (err) { | ||
await cleanup(); | ||
throw err; | ||
} | ||
prefixReg.enable(fw); | ||
return fw.addFace(new L3Face(transport, { | ||
const face = fw.addFace(new L3Face(transport, { | ||
advertiseFrom: false, | ||
describe: `NDN-DPDK(${id})`, | ||
...attributes, | ||
}, { | ||
mtu, | ||
})); | ||
face.on("close", cleanup); | ||
return face; | ||
} | ||
async function openFaceUdp(opts) { | ||
let { gqlServer = DefaultGqlServer, localHost, udp: udpOptionsInput, } = opts; | ||
localHost ?? (localHost = await detectLocalAddress(gqlServer)); | ||
const sock = await udp_helper.openSocket({ | ||
bind: { address: localHost }, | ||
...udpOptionsInput, | ||
}); | ||
try { | ||
return await openFaceImpl(opts, { | ||
scheme: "udp", | ||
remote: joinHostPort(localHost, sock.address().port), | ||
}, async (loc) => { | ||
const { host, port } = splitHostPort(loc.local ?? ""); | ||
if (!host || !port) { | ||
throw new Error(`unexpected locator: ${JSON.stringify(loc)}`); | ||
} | ||
await udp_helper.connect(sock, { host, port }); | ||
return [new UdpTransport(sock), 1450]; | ||
}); | ||
} | ||
catch (err) { | ||
sock.close(); | ||
throw err; | ||
} | ||
} | ||
async function openFaceMemif(opts) { | ||
const { memif: memifOptionsInput = {}, } = opts; | ||
const { socketPath = "/run/ndn", dataroom = 2048, ringCapacity = 1024, } = memifOptionsInput; | ||
const socketName = path.join(socketPath, `NDNts-memif-${process.pid}-${Date.now()}.sock`); | ||
return openFaceImpl(opts, { | ||
scheme: "memif", | ||
role: "server", | ||
socketName, | ||
socketOwner: [process.getuid(), process.getgid()], | ||
id: 0, | ||
dataroom, | ||
ringCapacity, | ||
}, async () => { | ||
const transport = await MemifTransport.connect({ | ||
role: "client", | ||
socketName, | ||
id: 0, | ||
dataroom, | ||
ringCapacity, | ||
}); | ||
return [transport, dataroom]; | ||
}); | ||
} | ||
/** Open a face on NDN-DPDK. */ | ||
export async function openFace(opts = {}) { | ||
const { scheme = "udp", } = opts; | ||
switch (scheme) { | ||
case "udp": | ||
return openFaceUdp(opts); | ||
case "memif": | ||
return openFaceMemif(opts); | ||
default: | ||
throw new Error(`unknown scheme ${scheme}`); | ||
} | ||
} |
import { Forwarder, FwFace } from "@ndn/fw"; | ||
import { L3Face } from "@ndn/l3face"; | ||
import { udp_helper } from "@ndn/node-transport"; | ||
import { MemifTransport } from "./memif-transport"; | ||
/** Open a face on NDN-DPDK. */ | ||
export declare function openFace({ fw, attributes, localHost, gqlServer, }?: openFace.Options): Promise<FwFace>; | ||
export declare function openFace(opts?: openFace.Options): Promise<FwFace>; | ||
export declare namespace openFace { | ||
interface Options { | ||
/** | ||
* NDN-DPDK GraphQL server. | ||
* Default is http://127.0.0.1:3030 . | ||
*/ | ||
gqlServer?: string; | ||
/** | ||
* IP address to reach local host from NDN-DPDK. | ||
* Default is auto-detected from GraphQL HTTP client. | ||
*/ | ||
localHost?: string; | ||
/** NDNts logical forwarder. */ | ||
@@ -11,7 +23,21 @@ fw?: Forwarder; | ||
attributes?: L3Face.Attributes; | ||
/** Local IPv4 address. */ | ||
localHost?: string; | ||
/** NDN-DPDK GraphQL server. */ | ||
gqlServer?: string; | ||
/** | ||
* Transport scheme. | ||
* Default is "udp". | ||
*/ | ||
scheme?: "udp" | "memif"; | ||
/** UDP socket options. */ | ||
udp?: udp_helper.OpenSocketOptions; | ||
/** memif options. */ | ||
memif?: MemifOptions; | ||
} | ||
/** memif options. */ | ||
interface MemifOptions extends Pick<MemifTransport.Options, "dataroom" | "ringCapacity"> { | ||
/** | ||
* Directory in which to place control socket. | ||
* If NDN-DPDK and NDNts are in containers, the same directory must be mounted in both containers. | ||
* Default is /run/ndn . | ||
*/ | ||
socketPath?: string; | ||
} | ||
} |
export * from "./face_browser.js"; | ||
export * from "./memif-transport_browser.js"; | ||
export * from "./prefix-reg_browser.js"; |
export * from "./face_node.js"; | ||
export * from "./memif-transport_node.js"; | ||
export * from "./prefix-reg_node.js"; |
export * from "./face"; | ||
export * from "./memif-transport"; | ||
export * from "./prefix-reg"; |
@@ -24,2 +24,3 @@ import { ReadvertiseDestination } from "@ndn/fw"; | ||
async doWithdraw(name, state) { | ||
void name; | ||
if (!state.fibEntryID) { | ||
@@ -26,0 +27,0 @@ return; |
@@ -24,2 +24,3 @@ import { ReadvertiseDestination } from "@ndn/fw"; | ||
async doWithdraw(name, state) { | ||
void name; | ||
if (!state.fibEntryID) { | ||
@@ -26,0 +27,0 @@ return; |
@@ -0,0 +0,0 @@ import { ReadvertiseDestination } from "@ndn/fw"; |
{ | ||
"name": "@ndn/dpdkmgmt", | ||
"version": "0.0.20210203", | ||
"version": "0.0.20210930", | ||
"description": "NDNts: NDN-DPDK Management", | ||
@@ -23,11 +23,15 @@ "keywords": [ | ||
"dependencies": { | ||
"@ndn/fw": "0.0.20210203", | ||
"@ndn/l3face": "0.0.20210203", | ||
"@ndn/node-transport": "0.0.20210203", | ||
"@ndn/packet": "0.0.20210203", | ||
"graphql": "^15.5.0", | ||
"graphql-request": "^3.4.0", | ||
"tslib": "^2.1.0" | ||
"@ndn/fw": "0.0.20210930", | ||
"@ndn/l3face": "0.0.20210930", | ||
"@ndn/node-transport": "0.0.20210930", | ||
"@ndn/packet": "0.0.20210930", | ||
"graphql": "^15.6.0", | ||
"graphql-request": "^3.5.0", | ||
"p-event": "^4.2.0", | ||
"tslib": "^2.3.1" | ||
}, | ||
"optionalDependencies": { | ||
"memif": "0.0.20210909" | ||
}, | ||
"types": "lib/mod.d.ts" | ||
} |
@@ -6,7 +6,6 @@ # @ndn/nfdmgmt | ||
This package enables interaction with [NDN-DPDK high-speed forwarder](https://github.com/usnistgov/ndn-dpdk). | ||
It can create faces for the NDNts application, and perform prefix registrations. | ||
It can create faces (either UDP or memif) for the NDNts application, and perform prefix registrations. | ||
Currently, there are several limitations using this package: | ||
* Data plane uses UDP transport, which does not deliver the best performance. | ||
* Prefix registration replaces a FIB entry, and does not preserve other prefix registrations on the same prefix. | ||
@@ -23,3 +22,4 @@ * If the application crashes, the face would not be closed on NDN-DPDK side. | ||
import { fromUtf8, toUtf8 } from "@ndn/tlv"; | ||
import { strict as assert } from "assert"; | ||
import { strict as assert } from "node:assert"; | ||
(async () => { | ||
@@ -29,7 +29,9 @@ | ||
const localHost = process.env.DEMO_DPDKMGMT_LOCAL; | ||
if (!gqlServer || !localHost) { | ||
const scheme = process.env.DEMO_DPDKMGMT_MEMIF === "1" ? "memif" : "udp"; | ||
if (!gqlServer) { | ||
console.log(` | ||
To run @ndn/dpdkmgmt demo, set the following environment variables: | ||
DEMO_DPDKMGMT_GQLSERVER= NDN-DPDK forwarder GraphQL server URI | ||
DEMO_DPDKMGMT_LOCAL= IPv4 address to reach local host from NDN-DPDK forwarder | ||
DEMO_DPDKMGMT_GQLSERVER= NDN-DPDK forwarder management endpoint (required) | ||
DEMO_DPDKMGMT_LOCAL= IP address to reach local host from NDN-DPDK (optional) | ||
DEMO_DPDKMGMT_MEMIF=1 use memif instead of UDP (optional) | ||
`); | ||
@@ -54,4 +56,5 @@ return; | ||
fw: fwC, | ||
gqlServer, | ||
localHost, | ||
gqlServer, | ||
scheme, | ||
}); | ||
@@ -61,11 +64,13 @@ uplinkC.addRoute(new Name("/")); | ||
fw: fwP, | ||
gqlServer, | ||
localHost, | ||
gqlServer, | ||
scheme, | ||
}); | ||
console.log(`uplinkC=${uplinkC}`, `uplinkP=${uplinkP}`); | ||
console.log(`uplinkC=${uplinkC}`, `uplinkP=${uplinkP}, transport=${scheme}`); | ||
// Start a producer. | ||
let t0 = 0; | ||
const producer = new Endpoint({ fw: fwP }).produce("/P", | ||
async (interest) => { | ||
console.log("producing"); | ||
console.log(`producing Data, latency=${Date.now() - t0}ms`); | ||
return new Data(interest.name, Data.FreshnessPeriod(1000), toUtf8("NDNts + NDN-DPDK")); | ||
@@ -75,8 +80,10 @@ }); | ||
// Start a consumer, fetching Data from the producer via NFD. | ||
// Start a consumer, fetching Data from the producer via NDN-DPDK. | ||
t0 = Date.now(); | ||
const data = await new Endpoint({ fw: fwC }).consume( | ||
new Interest(`/P/${Math.floor(Math.random() * 1e9)}`, Interest.MustBeFresh), | ||
); | ||
const t1 = Date.now(); | ||
const payloadText = fromUtf8(data.content); | ||
console.log("received", `${data.name} ${payloadText}`); | ||
console.log(`received ${data.name} ${payloadText}, rtt=${t1 - t0}ms`); | ||
assert.equal(payloadText, "NDNts + NDN-DPDK"); | ||
@@ -83,0 +90,0 @@ |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
20382
14
486
92
9
1
+ Addedp-event@^4.2.0
+ Added@ndn/fw@0.0.20210930(transitive)
+ Added@ndn/l3face@0.0.20210930(transitive)
+ Added@ndn/lp@0.0.20210930(transitive)
+ Added@ndn/node-transport@0.0.20210930(transitive)
+ Added@ndn/packet@0.0.20210930(transitive)
+ Added@ndn/tlv@0.0.20210930(transitive)
+ Addedabortable-iterator@3.0.2(transitive)
+ Addedit-pushable@1.4.2(transitive)
+ Addedmemif@0.0.20210909(transitive)
+ Addednode-addon-api@4.3.0(transitive)
+ Addedprepend-http@3.0.1(transitive)
+ Addedretry@0.13.1(transitive)
+ Addedstreaming-iterables@6.2.0(transitive)
+ Addedurl-format-lax@1.0.0(transitive)
+ Addedurl-parse-lax@4.0.0(transitive)
- Removed@ndn/fw@0.0.20210203(transitive)
- Removed@ndn/l3face@0.0.20210203(transitive)
- Removed@ndn/lp@0.0.20210203(transitive)
- Removed@ndn/node-transport@0.0.20210203(transitive)
- Removed@ndn/packet@0.0.20210203(transitive)
- Removed@ndn/tlv@0.0.20210203(transitive)
- Removedit-pushable@1.4.0(transitive)
- Removedretry@0.12.0(transitive)
- Removedstreaming-iterables@5.0.4(transitive)
Updated@ndn/fw@0.0.20210930
Updated@ndn/l3face@0.0.20210930
Updated@ndn/packet@0.0.20210930
Updatedgraphql@^15.6.0
Updatedgraphql-request@^3.5.0
Updatedtslib@^2.3.1