gRPC 是一个用于与 CORE 交互的客户端/服务器 API,并被 Python GUI 用于驱动所有功能。它依赖于要利用的正在运行的 CORE 守护程序实例。
可以从包含在 CORE 中的原始生成的 grpc 文件创建一个 python 客户端,或者可以利用提供的 gRPC 客户端来帮助封装一些功能来尝试帮助使事情变得更容易。
1. Python 客户端
CoreGrpcClient 提供了一个 python 客户端包装器,以帮助在使用 API 时提供一些便利。
1.1. 客户端 HTTP 代理
由于 gRPC 基于 HTTP2,代理配置可能会导致问题。默认情况下,客户端禁用代理支持以避免出现代理时出现问题。可以在需要时启用并正确解决此问题。
2. 原型文件
原型文件用于定义用于与此 API 接口的 API 和 protobuf 消息。
可以在此处找到它们以查看正在发生的事情的细节以及将返回的响应消息值。
3. 例子
3.1. 节点模型
创建 NodeType.DEFAULT 类型的节点时,这些是默认模型和它们映射到的服务。
- mdr
- zebra, OSPFv3MDR, IPForward
- PC
- DefaultRoute
- router
- zebra, OSPFv2, OSPFv3, IPForward
- host
- DefaultRoute, SSH
3.2. 接口帮助
在为节点创建接口数据时,可以利用一个接口助手类来方便。 或者,可以使用适当的信息手动创建 core.api.grpc.core_pb2.Interface 类。
手动创建 gRPC 接口数据:
from core.api.grpc import core_pb2
# id is optional and will set to the next available id
# name is optional and will default to eth<id>
# mac is optional and will result in a randomly generated mac
iface_data = core_pb2.Interface(
id=0,
name="eth0",
ip4="10.0.0.1",
ip4_mask=24,
ip6="2001::",
ip6_mask=64,
)
利用接口前缀帮助器类:
from core.emulator.data import IpPrefixes
ip_prefixes = IpPrefixes(ip4_prefix="10.0.0.0/24", ip6_prefix="2001::/64")
# 2. node is used to get an ip4/ip6 address indexed from within the above prefixes
# 3. name is optional and would default to eth<id>
# 4. mac is optional and will result in a randomly generated mac
iface_data = ip_prefixes.create_iface(
node=node, name="eth0", mac="00:00:00:00:aa:00"
)
3.3. 监听事件
可以监听会话中可能发生的各种事件。
事件类型:
- session - 会话状态和移动性开始/停止/暂停变化的事件
- node - 节点移动和图标更改的事件
- link - 链接配置更改和无线链接添加/删除的事件
- config - 旧版 gui 加入会话时的配置事件
- exception - 警报/错误事件
- file - 旧版 gui 加入会话时的文件事件
def event_listener(event):
print(event)
# add an event listener to event type you want to listen to
# each handler will receive an object unique to that type
session.event_handlers.append(event_listener)
session.exception_handlers.append(event_listener)
session.node_handlers.append(event_listener)
session.link_handlers.append(event_listener)
session.file_handlers.append(event_listener)
session.config_handlers.append(event_listener)
3.4. 配置链接
链接可以在创建时或运行时进行配置。
当前支持的配置选项:
- bandwidth (bps)
- delay (us)
- dup (%)
- jitter (us)
- loss (%)
from core.api.grpc import core_pb2
# 2. configuring when creating a link
options = core_pb2.LinkOptions(
bandwidth=54_000_000,
delay=5000,
dup=5,
loss=5.5,
jitter=0,
)
core.add_link(session_id, n1_id, n2_id, iface1_data, iface2_data, options)
# 3. configuring during runtime
core.edit_link(session_id, n1_id, n2_id, iface1_id, iface2_id, options)
3.5. 点对点例子
# required imports
from core.api.grpc import client
from core.api.grpc.core_pb2 import Node, NodeType, Position, SessionState
# interface helper
iface_helper = client.InterfaceHelper(ip4_prefix="10.0.0.0/24", ip6_prefix="2001::/64")
# create grpc client and connect
core = client.CoreGrpcClient()
core.connect()
# create session and get id
response = core.create_session()
session_id = response.session_id
# change session state to configuration so that nodes get started when added
core.set_session_state(session_id, SessionState.CONFIGURATION)
# create node one
position = Position(x=100, y=100)
n1 = Node(type=NodeType.DEFAULT, position=position, model="PC")
response = core.add_node(session_id, n1)
n1_id = response.node_id
# create node two
position = Position(x=300, y=100)
n2 = Node(type=NodeType.DEFAULT, position=position, model="PC")
response = core.add_node(session_id, n2)
n2_id = response.node_id
# links nodes together
iface1 = iface_helper.create_iface(n1_id, 0)
iface2 = iface_helper.create_iface(n2_id, 0)
core.add_link(session_id, n1_id, n2_id, iface1, iface2)
# change session state
core.set_session_state(session_id, SessionState.INSTANTIATION)
3.6. Switch/Hub 例子
# required imports
from core.api.grpc import client
from core.api.grpc.core_pb2 import Node, NodeType, Position, SessionState
# interface helper
iface_helper = client.InterfaceHelper(ip4_prefix="10.0.0.0/24", ip6_prefix="2001::/64")
# create grpc client and connect
core = client.CoreGrpcClient()
core.connect()
# create session and get id
response = core.create_session()
session_id = response.session_id
# change session state to configuration so that nodes get started when added
core.set_session_state(session_id, SessionState.CONFIGURATION)
# create switch node
position = Position(x=200, y=200)
switch = Node(type=NodeType.SWITCH, position=position)
response = core.add_node(session_id, switch)
switch_id = response.node_id
# create node one
position = Position(x=100, y=100)
n1 = Node(type=NodeType.DEFAULT, position=position, model="PC")
response = core.add_node(session_id, n1)
n1_id = response.node_id
# create node two
position = Position(x=300, y=100)
n2 = Node(type=NodeType.DEFAULT, position=position, model="PC")
response = core.add_node(session_id, n2)
n2_id = response.node_id
# links nodes to switch
iface1 = iface_helper.create_iface(n1_id, 0)
core.add_link(session_id, n1_id, switch_id, iface1)
iface1 = iface_helper.create_iface(n2_id, 0)
core.add_link(session_id, n2_id, switch_id, iface1)
# change session state
core.set_session_state(session_id, SessionState.INSTANTIATION)
3.7. WLAN 例子
# required imports
from core.api.grpc import client
from core.api.grpc.core_pb2 import Node, NodeType, Position, SessionState
# interface helper
iface_helper = client.InterfaceHelper(ip4_prefix="10.0.0.0/24", ip6_prefix="2001::/64")
# create grpc client and connect
core = client.CoreGrpcClient()
core.connect()
# create session and get id
response = core.create_session()
session_id = response.session_id
# change session state to configuration so that nodes get started when added
core.set_session_state(session_id, SessionState.CONFIGURATION)
# create wlan node
position = Position(x=200, y=200)
wlan = Node(type=NodeType.WIRELESS_LAN, position=position)
response = core.add_node(session_id, wlan)
wlan_id = response.node_id
# create node one
position = Position(x=100, y=100)
n1 = Node(type=NodeType.DEFAULT, position=position, model="mdr")
response = core.add_node(session_id, n1)
n1_id = response.node_id
# create node two
position = Position(x=300, y=100)
n2 = Node(type=NodeType.DEFAULT, position=position, model="mdr")
response = core.add_node(session_id, n2)
n2_id = response.node_id
# configure wlan using a dict mapping currently
# support values as strings
core.set_wlan_config(session_id, wlan_id, {
"range": "280",
"bandwidth": "55000000",
"delay": "6000",
"jitter": "5",
"error": "5",
})
# links nodes to wlan
iface1 = iface_helper.create_iface(n1_id, 0)
core.add_link(session_id, n1_id, wlan_id, iface1)
iface1 = iface_helper.create_iface(n2_id, 0)
core.add_link(session_id, n2_id, wlan_id, iface1)
# change session state
core.set_session_state(session_id, SessionState.INSTANTIATION)
3.8. EMANE 例子
对于 EMANE,您可以导入和使用现有模型之一,并使用其名称进行配置。
当前模型:
- core.emane.ieee80211abg.EmaneIeee80211abgModel
- core.emane.rfpipe.EmaneRfPipeModel
- core.emane.tdma.EmaneTdmaModel
- core.emane.bypass.EmaneBypassModel
它们的配置选项是从已安装的 EMANE 版本中解析的 EMANE 清单文件动态驱动的。
选项及其用途可以在 EMANE Wiki 中找到。
如果配置 EMANE 全局设置或模型 mac/phy 特定设置,任何未提供的值将使用默认值。当不使用配置时,使用默认值。
# required imports
from core.api.grpc import client
from core.api.grpc.core_pb2 import Node, NodeType, Position, SessionState
from core.emane.ieee80211abg import EmaneIeee80211abgModel
# interface helper
iface_helper = client.InterfaceHelper(ip4_prefix="10.0.0.0/24", ip6_prefix="2001::/64")
# create grpc client and connect
core = client.CoreGrpcClient()
core.connect()
# create session and get id
response = core.create_session()
session_id = response.session_id
# change session state to configuration so that nodes get started when added
core.set_session_state(session_id, SessionState.CONFIGURATION)
# create emane node
position = Position(x=200, y=200)
emane = Node(type=NodeType.EMANE, position=position, emane=EmaneIeee80211abgModel.name)
response = core.add_node(session_id, emane)
emane_id = response.node_id
# create node one
position = Position(x=100, y=100)
n1 = Node(type=NodeType.DEFAULT, position=position, model="mdr")
response = core.add_node(session_id, n1)
n1_id = response.node_id
# create node two
position = Position(x=300, y=100)
n2 = Node(type=NodeType.DEFAULT, position=position, model="mdr")
response = core.add_node(session_id, n2)
n2_id = response.node_id
# configure general emane settings
core.set_emane_config(session_id, {
"eventservicettl": "2"
})
# configure emane model settings
# using a dict mapping currently support values as strings
core.set_emane_model_config(session_id, emane_id, EmaneIeee80211abgModel.name, {
"unicastrate": "3",
})
# links nodes to emane
iface1 = iface_helper.create_iface(n1_id, 0)
core.add_link(session_id, n1_id, emane_id, iface1)
iface1 = iface_helper.create_iface(n2_id, 0)
core.add_link(session_id, n2_id, emane_id, iface1)
# change session state
core.set_session_state(session_id, SessionState.INSTANTIATION)
EMANE 模型配置:
# emane network specific config
core.set_emane_model_config(session_id, emane_id, EmaneIeee80211abgModel.name, {
"unicastrate": "3",
})
# node specific config
core.set_emane_model_config(session_id, node_id, EmaneIeee80211abgModel.name, {
"unicastrate": "3",
})
# node interface specific config
core.set_emane_model_config(session_id, node_id, EmaneIeee80211abgModel.name, {
"unicastrate": "3",
}, iface_id)
4. 配置一个服务
服务有助于在节点上生成和运行 bash 脚本以达到特定目的。
配置服务的文件会导致生成特定的硬编码脚本,而不是默认脚本,这可能会利用动态生成。
可以为服务配置以下功能:
- configs - 将生成的文件
- dirs - 将安装到节点唯一的目录
- startup - 运行启动服务的命令
- validate - 运行以验证服务的命令
- shutdown - 运行以停止服务的命令
编辑服务属性:
# configure a service, for a node, for a given session
session.services.set_service(node_id, service_name)
service = session.services.get_service(node_id, service_name)
service.configs = ("file1.sh", "file2.sh")
service.dirs = ("/etc/node",)
service.startup = ("bash file1.sh",)
service.validate = ()
service.shutdown = ()
编辑服务文件时,它必须是服务将生成的配置文件的名称。
编辑服务文件:
# to edit the contents of a generated file you can specify
# the service, the file name, and its contents
session.services.set_service_file(
node_id,
service_name,
file_name,
"echo hello",
)
5. 文件例子
可以在此处找到网络示例的文件版本。这些示例将在核心守护程序运行时使用 gRPC API 创建会话。
然后,您可以使用任一 CORE GUI 切换到并附加到这些会话。