Skip to content

Commit

Permalink
bin: Add other functions of pynfdc
Browse files Browse the repository at this point in the history
  • Loading branch information
zjkmxy committed Nov 21, 2021
1 parent f33467a commit 7164512
Show file tree
Hide file tree
Showing 14 changed files with 524 additions and 68 deletions.
4 changes: 2 additions & 2 deletions src/ndn/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -407,11 +407,11 @@ async def register(self, name: NonStrictName, func: Optional[Route], validator:
ret = parse_response(reply)
if ret['status_code'] != 200:
logging.error(f'Registration for {Name.to_str(name)} failed: '
f'{ret["status_code"]} {bytes(ret["status_text"]).decode()}')
f'{ret["status_code"]} {ret["status_text"]}')
return False
else:
logging.debug(f'Registration for {Name.to_str(name)} succeeded: '
f'{ret["status_code"]} {bytes(ret["status_text"]).decode()}')
f'{ret["status_code"]} {ret["status_text"]}')
return True
except (InterestNack, InterestTimeout, InterestCanceled, ValidationFailure) as e:
logging.error(f'Registration for {Name.to_str(name)} failed: {e.__class__.__name__}')
Expand Down
2 changes: 1 addition & 1 deletion src/ndn/app_support/nfd_mgmt.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ class ControlParameters(TlvModel):

class ControlResponse(ControlParametersValue):
status_code = UintField(0x66)
status_text = BytesField(0x67)
status_text = BytesField(0x67, is_string=True)
body = IncludeBase(ControlParametersValue)


Expand Down
11 changes: 10 additions & 1 deletion src/ndn/bin/nfdc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
# limitations under the License.
# -----------------------------------------------------------------------------
import argparse
from . import cmd_get_status, cmd_get_face
from . import cmd_get_status, cmd_get_face, cmd_get_route, cmd_get_strategy, \
cmd_remove_face, cmd_new_face, cmd_remove_route, cmd_new_route, cmd_remove_strategy, cmd_set_strategy


CMD_LIST = '''
Expand All @@ -42,6 +43,14 @@ def main():

cmd_get_status.add_parser(subparsers)
cmd_get_face.add_parser(subparsers)
cmd_get_route.add_parser(subparsers)
cmd_get_strategy.add_parser(subparsers)
cmd_remove_face.add_parser(subparsers)
cmd_new_face.add_parser(subparsers)
cmd_remove_route.add_parser(subparsers)
cmd_new_route.add_parser(subparsers)
cmd_remove_strategy.add_parser(subparsers)
cmd_set_strategy.add_parser(subparsers)

args = parser.parse_args()
if 'executor' not in args:
Expand Down
80 changes: 28 additions & 52 deletions src/ndn/bin/nfdc/cmd_get_face.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
import argparse
from ...app import NDNApp
from ...encoding import Name, Component
from ...types import InterestNack, InterestTimeout, InterestCanceled, ValidationFailure
from ...app_support.nfd_mgmt import FaceStatusMsg, FaceQueryFilter, FaceQueryFilterValue, parse_response, FaceFlags
from ...app_support.nfd_mgmt import FaceStatusMsg, FaceQueryFilter, FaceQueryFilterValue, parse_response
from .utils import express_interest


def add_parser(subparsers):
Expand All @@ -33,68 +33,44 @@ def execute(args: argparse.Namespace):
app = NDNApp()

async def list_face():
name = "/localhost/nfd/faces/list"
try:
_, _, data = await app.express_interest(
name, lifetime=1000, can_be_prefix=True, must_be_fresh=True)

data = await express_interest(app, "/localhost/nfd/faces/list")
msg = FaceStatusMsg.parse(data)
# TODO: Should calculate the length instead of using a fixed number
print(f'{"FaceID":7}{"RemoteURI":<30}\t{"LocalURI":<30}')
print(f'{"------":7}{"---------":<30}\t{"--------":<30}')
for f in msg.face_status:
print(f'{f.face_id:<7}{f.uri:<30}\t{f.local_uri:<30}')

except InterestNack as e:
print(f'Nacked with reason={e.reason}')
except InterestTimeout:
print('Timeout')
except InterestCanceled:
print('Local forwarder disconnected')
except ValidationFailure:
print('Data failed to validate')
finally:
app.shutdown()

async def inspect_face(face_id, face_uri):
async def exec_query():
try:
_, _, data = await app.express_interest(
data_name, lifetime=1000, can_be_prefix=True, must_be_fresh=True)

if not data:
return False
elif data[0] == 0x65:
msg = parse_response(data)
print('Query failed with response', msg['status_code'], msg['status_text'])
else:
msg = FaceStatusMsg.parse(data)
for f in msg.face_status:
print()
print(f'{"Face ID":>12}\t{f.face_id}')
print(f'{"Remote URI":>12}\t{f.uri}')
print(f'{"Local URI":>12}\t{f.local_uri}')
print(f'{"Scope":>12}\t{f.face_scope.name}')
print(f'{"Persistency":>12}\t{f.face_persistency.name}')
print(f'{"Link Type":>12}\t{f.link_type.name}')
if f.mtu:
print(f'{"MTU":>12}\t{f.mtu}')
else:
print(f'{"MTU":>12}\t-')
print(f'{"Counter IN":>12}\t{f.n_in_interests}i {f.n_in_data}d '
f'{f.n_in_nacks}n {f.n_in_bytes}B')
print(f'{"Counter OUT":>12}\t{f.n_out_interests}i {f.n_out_data}d '
f'{f.n_out_nacks}n {f.n_out_bytes}B')
print(f'{"Flags":>12}\t{FaceFlags(f.flags)}')

except InterestNack as e:
print(f'Nacked with reason={e.reason}')
except InterestTimeout:
print('Timeout')
except InterestCanceled:
print('Local forwarder disconnected')
except ValidationFailure:
print('Data failed to validate')
data = await express_interest(app, data_name)
if not data:
return False
elif data[0] == 0x65:
msg = parse_response(data)
print('Query failed with response', msg['status_code'], msg['status_text'])
else:
msg = FaceStatusMsg.parse(data)
for f in msg.face_status:
print()
print(f'{"Face ID":>12}\t{f.face_id}')
print(f'{"Remote URI":>12}\t{f.uri}')
print(f'{"Local URI":>12}\t{f.local_uri}')
print(f'{"Scope":>12}\t{f.face_scope.name}')
print(f'{"Persistency":>12}\t{f.face_persistency.name}')
print(f'{"Link Type":>12}\t{f.link_type.name}')
if f.mtu:
print(f'{"MTU":>12}\t{f.mtu}')
else:
print(f'{"MTU":>12}\t-')
print(f'{"Counter IN":>12}\t{f.n_in_interests}i {f.n_in_data}d '
f'{f.n_in_nacks}n {f.n_in_bytes}B')
print(f'{"Counter OUT":>12}\t{f.n_out_interests}i {f.n_out_data}d '
f'{f.n_out_nacks}n {f.n_out_bytes}B')
print(f'{"Flags":>12}\t{f.flags}')
return True

name = "/localhost/nfd/faces/query"
Expand Down
63 changes: 63 additions & 0 deletions src/ndn/bin/nfdc/cmd_get_route.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# -----------------------------------------------------------------------------
# Copyright (C) 2019-2021 The python-ndn authors
#
# This file is part of python-ndn.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# -----------------------------------------------------------------------------
import argparse
from ...app import NDNApp
from ...encoding import Name
from ...app_support.nfd_mgmt import FibStatus, RibStatus
from .utils import express_interest


def add_parser(subparsers):
parser = subparsers.add_parser('Get-Route', aliases=['route', 'gr'])
parser.add_argument('route', metavar='ROUTE', nargs='?', default='',
help='The prefix of the specified route to query')
parser.set_defaults(executor=execute)


def execute(args: argparse.Namespace):
app = NDNApp()
route = args.route

async def list_route():
try:
fib_data = await express_interest(app, "/localhost/nfd/fib/list")
fib_msg = FibStatus.parse(fib_data)
rib_data = await express_interest(app, "/localhost/nfd/rib/list")
rib_msg = RibStatus.parse(rib_data)
# TODO: Should calculate the length instead of using a fixed number
print('Forwarding Table (FIB)')
for ent in fib_msg.entries:
prefix = Name.to_str(ent.name)
if route and prefix != route:
continue
print(prefix)
for nh in ent.next_hop_records:
print(f'\tFaceID={nh.face_id:<5} Cost={nh.cost:<5}')
print()
print('Routing Table (RIB)')
for ent in rib_msg.entries:
prefix = Name.to_str(ent.name)
if route and prefix != route:
continue
print(prefix)
for nh in ent.routes:
print(f'\tFaceID={nh.face_id:<5} Cost={nh.cost:<5} Origin={nh.origin:<3} Flags={nh.flags}')
finally:
app.shutdown()

app.run_forever(list_route())
14 changes: 2 additions & 12 deletions src/ndn/bin/nfdc/cmd_get_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
import argparse
import datetime
from ...app import NDNApp
from ...types import InterestNack, InterestTimeout, InterestCanceled, ValidationFailure
from ...app_support.nfd_mgmt import GeneralStatus
from .utils import express_interest


def add_parser(subparsers):
Expand All @@ -31,10 +31,8 @@ def execute(_args: argparse.Namespace):
app = NDNApp()

async def after_start():
name = "/localhost/nfd/status/general"
try:
_, _, data = await app.express_interest(
name, lifetime=1000, can_be_prefix=True, must_be_fresh=True)
data = await express_interest(app, "/localhost/nfd/status/general")

msg = GeneralStatus.parse(data)

Expand All @@ -59,14 +57,6 @@ async def after_start():
print(f'{"nOutNacks":>25}\t{msg.n_out_nacks}')
print(f'{"nSatisfiedInterests":>25}\t{msg.n_satisfied_interests}')
print(f'{"nUnsatisfiedInterests":>25}\t{msg.n_unsatisfied_interests}')
except InterestNack as e:
print(f'Nacked with reason={e.reason}')
except InterestTimeout:
print('Timeout')
except InterestCanceled:
print('Local forwarder disconnected')
except ValidationFailure:
print('Data failed to validate')
finally:
app.shutdown()

Expand Down
48 changes: 48 additions & 0 deletions src/ndn/bin/nfdc/cmd_get_strategy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# -----------------------------------------------------------------------------
# Copyright (C) 2019-2021 The python-ndn authors
#
# This file is part of python-ndn.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# -----------------------------------------------------------------------------
import argparse
from ...app import NDNApp
from ...encoding import Name
from ...app_support.nfd_mgmt import StrategyChoiceMsg
from .utils import express_interest


def add_parser(subparsers):
parser = subparsers.add_parser('Get-Strategy', aliases=['strategy', 'gs'])
parser.add_argument('prefix', metavar='PREFIX', nargs='?', default='',
help='The specified route prefix')
parser.set_defaults(executor=execute)


def execute(args: argparse.Namespace):
app = NDNApp()
prefix = args.prefix

async def list_strategy():
try:
data = await express_interest(app, "/localhost/nfd/strategy-choice/list")
msg = StrategyChoiceMsg.parse(data)
for s in msg.strategy_choices:
s_prefix = Name.to_str(s.name)
if prefix and s_prefix != prefix:
continue
print(f'{s_prefix}\n\t{Name.to_str(s.strategy.name)}')
finally:
app.shutdown()

app.run_forever(list_strategy())
47 changes: 47 additions & 0 deletions src/ndn/bin/nfdc/cmd_new_face.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# -----------------------------------------------------------------------------
# Copyright (C) 2019-2021 The python-ndn authors
#
# This file is part of python-ndn.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# -----------------------------------------------------------------------------
import argparse
from ...app import NDNApp
from ...app_support.nfd_mgmt import parse_response, make_command
from .utils import express_interest


def add_parser(subparsers):
parser = subparsers.add_parser('New-Face', aliases=['nf'])
parser.add_argument('uri', metavar='URI',
help='The URI or IP address of the face to create. '
'Note: current version does not support DNS resolve.')
parser.set_defaults(executor=execute)


def execute(args: argparse.Namespace):
app = NDNApp()
uri = str(args.uri)
if uri.find('://') < 0:
uri = 'udp4://' + uri
if len(uri.split(":")) < 3:
uri = uri + ":6363"

async def create_face():
cmd = make_command('faces', 'create', uri=uri.encode())
res = await express_interest(app, cmd)
msg = parse_response(res)
print(f'{msg["status_code"]} {msg["status_text"]}')
app.shutdown()

app.run_forever(after_start=create_face())
Loading

0 comments on commit 7164512

Please sign in to comment.