本文主要是介绍SDSN:基于SDN的卫星网络,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
SDSN:基于SDN的卫星网络
前段时间一直在做跟SDN与卫星网络相关的毕设,学习了很多东西也走了很多弯路,所以想分享一下自己的学习过程,并且对相关的知识做一个总结。
思路框架
相关知识获取:
关于SDSN网上的开源资料都十分有限,卫星方面基本上都是看的各种论文中怎么对卫星进行的构建,实现上也基本就简单的参考了STK工具包的使用,SDN方面开源的资料比较多,主要是SDNLAB,李呈的博客以及RYU Book,还有市面上能够买到的一些SDN的书籍。
整体的实现思路:利用STK等工具对卫星整体架构进行设计和仿真从而形成卫星网络的实验环境。
利用python的网络传输将STK构建的仿真环境传输给虚拟机,在虚拟机中利用接收到的仿真数据(可以为json格式)在Mininet(常用的SDN网络仿真工具)中构建SDN网络拓扑,最终在Mininet中连接到自己使用的控制器从而进行各种仿真实验。
下面大致的列举一些参考的资料:
关于卫星方面:
https://blog.csdn.net/qq_43901693/category_10245394.html
Python与STK的联合仿真
关于SDN方面的:
李呈的博客:http://www.muzixing.com/index4.html
SDN基础教程:
https://space.bilibili.com/508139652
https://www.bilibili.com/video/BV1ft4y1a7ip/?spm_id_from=333.999.0.0
SDNLAB:https://www.sdnlab.com/20370.html
使用RYU进行的多种实验:https://blog.csdn.net/qq_41422448/category_11474633.html
SDN相关的书籍:
https://www.zhihu.com/pub/reader/119637507/chapter/1167046161537064960
RYU的源码解析:https://www.jianshu.com/p/ff59c7c5f056
RYU API: https://ryu.readthedocs.io/en/latest/api_ref.html
研究过程
完成整个研究任务需要大致了解一下几个方面:
- 卫星网络是如何构建的,他有怎么样的参数,轨道是什么样的,卫星是如何运动的,星体模型是什么样的?例如一个常见的铱星(Iridium)系统。
- SDN是一个什么样的概念,他的应用场景和关键技术是怎么样的?他在卫星网络中又是如何被使用的?
- SDN控制器与交换器各个是什么样的概念,是如何实现如何应用的。OpenFlow协议又是什么概念?
- 在SDSN(Sat+SDN)的场景中,卫星与SDN是如何相互配合相互实现的?目前的研究领域和研究目标有哪些?技术难点和应用创新点有哪些?
- 针对上述知识,如何在技术上进行仿真与实现?
天体网络架构
整体工作可以大致切分为两块:系统架构(实验环境(当然也有可能是研究内容))+ SDN
系统架构大致可以分为几个部分:
1.网络层次关系设计
网络层次关系我个人的理解好像就是嘴上说说,大致就是整个系统应该是三个层面的事情,这里不提太多。
2.网络运行机制设计
运行机制是一个相对复杂的概念。设计到组网和控制域划分的问题,有很多不同的设计方向。
https://www.sdnlab.com/15853.html
这里就直接用一下别人论文里的定义:
3.卫星星体星座设计
卫星星座则是一个比较复杂的部分,常常通过覆盖性分析来确定整个的卫星星体结构。其构建过程可以参考铱星(Iridium)系统或者Walker星座。
例如:Starklink
SpaceX最初向FCC提交的报告里,Starlink是由4425颗分布在1100km高度轨道的LEO星座和7518颗分布在340km左右的VLEO(甚低轨)星座构成。具体分布参见表1和表2的星座轨道。
2018年底SpaceX又向FCC提交了修改计划,4月26日FCC宣布批准SpaceX调低其宽带星座项目部分卫星轨道的请求。将原1600颗1150km轨道卫星调整为1584颗550km的轨道卫星。通过降低部分卫星轨道,它所需卫星总数将可减少16颗,并将能让信号时延低至15毫秒。同时这将改善空间环境的安全性,因为轨道调低后的卫星即便不带推进,也会在报废后5年内再入地球大气层。
Starlink首先将实现1584颗550km的轨道卫星布置,实际发射时,由于火箭推力不够,卫星初始入轨点定为440km,后由推进器爬升至550km。知道1584颗卫星分布在24个平面,便比较容易用Walker星座设计器仿真出星座设计了。
其设计步骤如下
1)通过Space-track网站TLE根数分析出初始60颗卫星的轨道平面;根据发射日期和轨道倾角可以确定Starlink初始发射的60颗卫星国际编号为19029A至19029BM,NORAD编号为44235U至44294U,下载根数,导入STK;通过report分析J2000坐标系轨道升交点赤经
2)设定种子卫星;本文以2019.05.27日根数分析结果,设定种子卫星历元及根数为:27 May 2019 06:14:00.000 UTC、半长轴6928.137(高度550km)、升交点赤经160°、轨道倾角53°、偏心率0°、其他轨道参数为0。为卫星添加传感器(Sensor),设定圆锥半角为44.85°,为后续覆盖分析做准备。
3)由种子卫星生成参数(T/P/F)24/66/1的Walker星座,这里参数F暂取为1,具体应该怎么设置最优我没有搞明白,STK有Parametric Study Tool STK模块,但我没找到,如有了解者,敬请指导。这里为了美观,可以设置名称显示及轨道曲线等参数,不详细说明,注意为了后续分析方便,最好勾选创建星座,因为接下来覆盖分析可以通过星座选定分析卫星或是传感器,选择的时候种子卫星或其传感器不要选进去。同时算1584个目标计算机压力还是有点大的,试算可以使用较小规模的参数,比如(T/P/F)4/4/1
4.卫星网络拓扑设计
最后就是网络拓扑设计,在卫星星体确定的情况下,如何实现之前的卫星运行机制以及层次关系。简单来说,就是如何将SDN比较好的引入到设计的卫星星体上来。
目前有多种架构方式,参考如下:
例如设计一个两层的卫星网络:
如上图所示,LEO同样采用钵星体系,在LEO层面布置交换机,在MEO/GEO层面采用控制器部署
在地面控制中心部署控制器和MEO卫星来组成控制平面,为了简化网络模型,我们从逻辑上将多个地面控制中心视为一个整体的实体。LEO卫星层作为整个网络的基础设施层,负责数据包的转发。最初,每颗LEO卫星向其MEO卫星发送一个流表请求。MEO卫星在接收到流量表请求后,将收集到的信息发送到地面控制中心。地面控制中心计算不同的路由规则。
同样还有如上结构,采用了单一的控制器布置在GEO与全局相连,GEO层布置转发路由器承担部分转发功能,地面站则作为网络流量的输入层。
技术实现
在技术实现上,我主要参考了以下文章:
https://zhuanlan.zhihu.com/p/260657677
https://zhuanlan.zhihu.com/p/260657677)https://zhuanlan.zhihu.com/p/68385977
https://www.notion.so/SDN_SAT-79ebbc4f8aee4666a6b3b1208c683b21?pvs=4#9a4e85019d8a48cd9c62edd0ba0c0328
下面给出一段STK的单层结构与三层架构的参考代码,其中并没有具体给出LEO,MEO,GEO层的连接关系
import time
import json
from tqdm import tqdmstartTime = time.time()
from comtypes.gen import STKObjects, STKUtil, AgStkGatorLib
from comtypes.client import CreateObject, GetActiveObject, GetEvents, CoGetObject, ShowEvents
import requests
import time"""
SET TO TRUE TO USE ENGINE, FALSE TO USE GUI
"""
useStkEngine = True
Read_Scenario = False
############################################################################
# Scenario Setup
############################################################################if useStkEngine:# Launch STK Engineprint("Launching STK Engine...")stkxApp = CreateObject("STKX11.Application")# Disable graphics. The NoGraphics property must be set to true before the root object is created.stkxApp.NoGraphics = True# Create root objectstkRoot = CreateObject('AgStkObjects11.AgStkObjectRoot')else:# Launch GUIprint("Launching STK...")if not Read_Scenario:uiApp = CreateObject("STK11.Application")else:uiApp = GetActiveObject("STK11.Application")uiApp.Visible = TrueuiApp.UserControl = True# Get root objectstkRoot = uiApp.Personality2# Set date format
stkRoot.UnitPreferences.SetCurrentUnit("DateFormat", "UTCG")
# Create new scenario
print("Creating scenario...")
if not Read_Scenario:# stkRoot.NewScenario('Kuiper')stkRoot.NewScenario('StarLink')
scenario = stkRoot.CurrentScenario
scenario2 = scenario.QueryInterface(STKObjects.IAgScenario)
scenario2.StartTime = '24 Sep 2020 16:00:00.00'
scenario2.StopTime = '25 Sep 2020 16:20:00.00'
dt='24 Sep 2020 16:00:00'
ts = int(time.mktime(time.strptime(dt, "%d %b %Y %H:%M:%S")))totalTime = time.time() - startTime
print("---Total time: {b:4.3f} sec ---".format(b=totalTime))# 创建星座
def Creat_satellite(numOrbitPlanes=72, numSatsPerPlane=22, hight=550, Inclination=53, name='node_'):# Create constellation objectprint("--- create satellite ,total num :{a} ---".format(a=numOrbitPlanes * numSatsPerPlane))constellation = scenario.Children.New(STKObjects.eConstellation, name)constellation2 = constellation.QueryInterface(STKObjects.IAgConstellation)# Insert the constellation of Satellitesfor orbitPlaneNum in range(numOrbitPlanes): # RAAN in degreesprint("---create sat on orbitPlane {a} ---".format(a=orbitPlaneNum))for satNum in range(numSatsPerPlane): # trueAnomaly in degrees# Insert satellitesatellite = scenario.Children.New(STKObjects.eSatellite, f"{name}{orbitPlaneNum}-{satNum}")satellite2 = satellite.QueryInterface(STKObjects.IAgSatellite)# Select Propagatorsatellite2.SetPropagatorType(STKObjects.ePropagatorTwoBody)# Set initial statetwoBodyPropagator = satellite2.Propagator.QueryInterface(STKObjects.IAgVePropagatorTwoBody)keplarian = twoBodyPropagator.InitialState.Representation.ConvertTo(STKUtil.eOrbitStateClassical).QueryInterface(STKObjects.IAgOrbitStateClassical)#定义半轴长度keplarian.SizeShapeType = STKObjects.eSizeShapeSemimajorAxis#定义高度keplarian.SizeShape.QueryInterface(STKObjects.IAgClassicalSizeShapeSemimajorAxis).SemiMajorAxis = hight + 6371 # km#定义偏心率keplarian.SizeShape.QueryInterface(STKObjects.IAgClassicalSizeShapeSemimajorAxis).Eccentricity = 0keplarian.Orientation.Inclination = int(Inclination) # degrees 倾角keplarian.Orientation.ArgOfPerigee = 0 # degrees 近地点keplarian.Orientation.AscNodeType = STKObjects.eAscNodeRAANRAAN = 360 / numOrbitPlanes * orbitPlaneNumkeplarian.Orientation.AscNode.QueryInterface(STKObjects.IAgOrientationAscNodeRAAN).Value = RAAN # degreeskeplarian.LocationType = STKObjects.eLocationTrueAnomalytrueAnomaly = 360 / numSatsPerPlane * satNumkeplarian.Location.QueryInterface(STKObjects.IAgClassicalLocationTrueAnomaly).Value = trueAnomaly# Propagatesatellite2.Propagator.QueryInterface(STKObjects.IAgVePropagatorTwoBody).InitialState.Representation.Assign(keplarian)satellite2.Propagator.QueryInterface(STKObjects.IAgVePropagatorTwoBody).Propagate()# Add to constellation objectconstellation2.Objects.AddObject(satellite)# 为每个卫星加上发射机和接收机
def Add_transmitter_receiver(sat_list):print("--- add transmitter and reciver for sat ---")for each in sat_list:Instance_name = each.InstanceName# new transmitter and receivertransmitter = each.Children.New(STKObjects.eTransmitter, "Transmitter_" + Instance_name)reciver = each.Children.New(STKObjects.eReceiver, "Reciver_" + Instance_name)#sensor = each.Children.New(STKObjects.eSensor, 'Sensor_' + Instance_name)# 设置发射机参数
def Set_Transmitter_Parameter(transmitter, frequency=12, EIRP=20, DataRate=14):transmitter2 = transmitter.QueryInterface(STKObjects.IAgTransmitter) # 建立发射机的映射,以便对其进行设置transmitter2.SetModel('Simple Transmitter Model')txModel = transmitter2.ModeltxModel = txModel.QueryInterface(STKObjects.IAgTransmitterModelSimple)txModel.Frequency = frequency # GHz range:10.7-12.7GHztxModel.EIRP = EIRP # dBWtxModel.DataRate = DataRate # Mb/sec# 设置接收机参数
def Set_Receiver_Parameter(receiver, GT=20, frequency=12):receiver2 = receiver.QueryInterface(STKObjects.IAgReceiver) # 建立发射机的映射,以便对其进行设置receiver2.SetModel('Simple Receiver Model')recModel = receiver2.ModelrecModel = recModel.QueryInterface(STKObjects.IAgReceiverModelSimple)recModel.AutoTrackFrequency = FalserecModel.Frequency = frequency # GHz range:10.7-12.7GHzrecModel.GOverT = GT # dB/Kreturn receiver2# 获得接收机示例,并设置其参数
def Get_sat_receiver(sat, GT=20, frequency=12):receiver = sat.Children.GetElements(STKObjects.eReceiver)[0] # 找到该卫星的接收机receiver2 = Set_Receiver_Parameter(receiver=receiver, GT=GT, frequency=frequency)return receiver2def get_time():timeNow = time.strftime("%d %b %Y %H:%M:%S", time.localtime(ts))timeNowLong = str(timeNow) + ".00"return timeNowLong# 计算传输链路
def Compute_access(access):# print("---computer access---")access.ComputeAccess()accessDP = access.DataProviders.Item('Link Information')accessDP2 = accessDP.QueryInterface(STKObjects.IAgDataPrvTimeVar)Elements = ["Range"]results = accessDP2.ExecSingleElements(get_time(), Elements)# results2 = accessDP2.ExecSingleElements(scenario2.StopTime, Elements)# Times = results.DataSets.GetDataSetByName('Time').GetValues() # 时间# EbNo = results.DataSets.GetDataSetByName('Eb/No').GetValues() # 码元能量# BER = results.DataSets.GetDataSetByName('BER').GetValues() # 误码率# Link_Name = results.DataSets.GetDataSetByName('Link Name').GetValues()# Prop_Loss = results.DataSets.GetDataSetByName('Prop Loss').GetValues()# Xmtr_Gain = results.DataSets.GetDataSetByName('Xmtr Gain').GetValues()# EIRP = results.DataSets.GetDataSetByName('EIRP').GetValues()Range = results.DataSets.GetDataSetByName('Range').GetValues()# Range2=results2.DataSets.GetDataSetByName('Range').GetValues()# print(results2)return Rangedef Creating_All_Access():# 首先清空场景中所有的链接print('--- Clearing All Access ---')print('--- create Access ---')stkRoot.ExecuteCommand('RemoveAllAccess /')# 计算某个卫星与其通信的四颗卫星的链路质量,并生成报告for each_sat in sat_list:now_sat_name = each_sat.InstanceNamenow_plane_num = int(now_sat_name.split('-')[0][5:])now_sat_num = int(now_sat_name.split('-')[1])now_sat_transmitter = each_sat.Children.GetElements(STKObjects.eTransmitter)[0] # 找到该卫星的发射机Set_Transmitter_Parameter(now_sat_transmitter, EIRP=20)# 发射机与接收机相连# 与后面的卫星的接收机相连B_Name = sat_dic['node_' + str(now_plane_num) + '-' + str((now_sat_num + 1) % 10)].InstanceNameF_Name = sat_dic['node_' + str(now_plane_num) + '-' + str((now_sat_num - 1) % 10)].InstanceNameL_Name = sat_dic['node_' + str((now_plane_num - 1) % 10) + '-' + str(now_sat_num)].InstanceNameR_Name = sat_dic['node_' + str((now_plane_num + 1) % 10) + '-' + str(now_sat_num)].InstanceNameaccess_backward = now_sat_transmitter.GetAccessToObject(Get_sat_receiver(sat_dic['node_' + str(now_plane_num) + '-' + str((now_sat_num + 1) % 10)]))# 与前面的卫星的接收机相连access_forward = now_sat_transmitter.GetAccessToObject(Get_sat_receiver(sat_dic['node_' + str(now_plane_num) + '-' + str((now_sat_num - 1) % 10)]))# 与左面的卫星的接收机相连access_left = now_sat_transmitter.GetAccessToObject(Get_sat_receiver(sat_dic['node_' + str((now_plane_num - 1) % 10) + '-' + str(now_sat_num)]))# 与右面的卫星的接收机相连access_right = now_sat_transmitter.GetAccessToObject(Get_sat_receiver(sat_dic['node_' + str((now_plane_num + 1) % 10) + '-' + str(now_sat_num)]))B_Range = Compute_access(access_backward)F_Range = Compute_access(access_forward)L_Range = Compute_access(access_left)R_Range = Compute_access(access_right)B_Dict = {'node1': now_sat_name, 'node2': B_Name, 'bw': 20, 'delay': str(int(B_Range[0] / 300))+'ms', 'jitter': '1ms','loss': 0}F_Dict = {'node1': now_sat_name, 'node2': F_Name, 'bw': 20,'delay': str(int(F_Range[0] / 300))+'ms', 'jitter': '1ms','loss': 0}L_Dict = {'node1': now_sat_name, 'node2': L_Name, 'bw': 20, 'delay': str(int(L_Range[0] / 300))+'ms', 'jitter': '1ms','loss': 0}R_Dict = {'node1': now_sat_name, 'node2': R_Name, 'bw': 20, 'delay':str(int(R_Range[0] / 300))+'ms', 'jitter': '1ms','loss': 0}data_list.append(B_Dict)data_list.append(F_Dict)#data_list.append(L_Dict)#data_list.append(R_Dict)# print('{0}\r', B_Range, F_Range, L_Range, R_Range)# stkRoot.ExecuteCommand('RemoveAllAccess /')def Change_Sat_color(sat_list):# 修改卫星及其轨道的颜色print('Changing Color of Satellite')for each_sat in sat_list:now_sat_name = each_sat.InstanceNamenow_plane_num = int(now_sat_name.split('_')[0][3:])now_sat_num = int(now_sat_name.split('_')[1])satellite = each_sat.QueryInterface(STKObjects.IAgSatellite)graphics = satellite.Graphicsgraphics.SetAttributesType(1) # eAttributesBasicattributes = graphics.Attributesattributes_color = attributes.QueryInterface(STKObjects.IAgVeGfxAttributesBasic)attributes_color.Inherit = False# 16436871 浅蓝色# 2330219 墨绿色# 42495 橙色# 9234160 米黄色# 65535 黄色# 255 红色# 16776960 青色color_sheet = [16436871, 2330219, 42495, 9234160, 65535, 255, 16776960]if now_sat_name[2] == 'A':color = 255elif now_sat_name[2] == 'B':color = 42495elif now_sat_name[2] == 'C':color = 16436871attributes_color.Color = color# 找出轨道对应的属性接口orbit = attributes.QueryInterface(STKObjects.IAgVeGfxAttributesOrbit)orbit.IsOrbitVisible = False # 将轨道设置为不可见def mid_link():for each_sat in sat_list:now_sat_name = each_sat.InstanceNametmpparam={'node1': now_sat_name, 'node2': "mid1", 'bw': 20, 'delay': "20ms", 'jitter': '1ms','loss': 0}data_list.append(tmpparam)# 如果不是读取当前场景,即首次创建场景
if not Read_Scenario:Creat_satellite(numOrbitPlanes=10, numSatsPerPlane=10, hight=550, Inclination=53) # Starlink# Kuiper# Creat_satellite(numOrbitPlanes=34, numSatsPerPlane=34, hight=630, Inclination=51.9, name='KPA') # Phase A# Creat_satellite(numOrbitPlanes=32, numSatsPerPlane=32, hight=610, Inclination=42, name='KPB') # Phase B#Creat_satellite(numOrbitPlanes=28, numSatsPerPlane=28, hight=590, Inclination=33) # Phase Csat_list = stkRoot.CurrentScenario.Children.GetElements(STKObjects.eSatellite)Add_transmitter_receiver(sat_list)# 创建卫星的字典,方便根据名字对卫星进行查找
sat_list = stkRoot.CurrentScenario.Children.GetElements(STKObjects.eSatellite)
sat_dic = {}
data_list = []
print('--- Creating Satellite Dictionary ---')
for sat in sat_list:sat_dic[sat.InstanceName] = sat
Plane_num = []
for i in range(0, 10):Plane_num.append(i)
Sat_num = []
for i in range(0, 10):Sat_num.append(i)headers = {"Content-Type": "application/json;charset=utf8"
}
for i in range(0,10):Creating_All_Access()ts+=600print(data_list)data_list = json.dumps(data_list)response = requests.post('http://192.168.56.135:8000/modify/', data = data_list,headers=headers)print("--- topo uptade ---")data_list = []if i==0:mid_link()data_list = json.dumps(data_list)print(data_list)response = requests.post('http://192.168.56.135:8000/modify/', data = data_list,headers=headers)print(i)time.sleep(30)
print("end")
def Creating_All_Access():# 首先清空场景中所有的链接print('--- Clearing All Access ---')print('--- create Access ---')stkRoot.ExecuteCommand('RemoveAllAccess /')# 计算某个卫星与其通信的四颗卫星的链路质量,并生成报告for each_sat in sat_list:now_sat_name = each_sat.InstanceNameprint(now_sat_name)now_plane_num = int(now_sat_name.split('-')[0][4:])now_sat_num = int(now_sat_name.split('-')[1])now_plane_name = (now_sat_name.split(' ')[0][:4])now_sat_transmitter = each_sat.Children.GetElements(STKObjects.eTransmitter)[0] # 找到该卫星的发射机Set_Transmitter_Parameter(now_sat_transmitter, EIRP=20)# 发射机与接收机相连# 与后面的卫星的接收机相连if(now_plane_name == 'LEO_'):numOrbitPlanes = 6numSatsPerPlane = 12B_Name = sat_dic['LEO_' + str(now_plane_num) + '-' + str((now_sat_num + 1) % numSatsPerPlane)].InstanceNameF_Name = sat_dic['LEO_' + str(now_plane_num) + '-' + str((now_sat_num - 1) % numSatsPerPlane)].InstanceName# L_Name = sat_dic['LEO_' + str((now_plane_num - 1) % numOrbitPlanes) + '-' + str(now_sat_num)].InstanceName# R_Name = sat_dic['LEO_' + str((now_plane_num + 1) % numOrbitPlanes) + '-' + str(now_sat_num)].InstanceNameaccess_backward = now_sat_transmitter.GetAccessToObject(Get_sat_receiver(sat_dic['LEO_' + str(now_plane_num) + '-' + str((now_sat_num + 1) % numSatsPerPlane)]))# 与前面的卫星的接收机相连access_forward = now_sat_transmitter.GetAccessToObject(Get_sat_receiver(sat_dic['LEO_' + str(now_plane_num) + '-' + str((now_sat_num - 1) % numSatsPerPlane)]))# 与左面的卫星的接收机相连# access_left = now_sat_transmitter.GetAccessToObject(# Get_sat_receiver(sat_dic['node_' + str((now_plane_num - 1) % numOrbitPlanes) + '-' + str(now_sat_num)]))# 与右面的卫星的接收机相连# access_right = now_sat_transmitter.GetAccessToObject(# Get_sat_receiver(sat_dic['node_' + str((now_plane_num + 1) % numOrbitPlanes) + '-' + str(now_sat_num)]))B_Range = Compute_access(access_backward)F_Range = Compute_access(access_forward)# L_Range = Compute_access(access_left)# R_Range = Compute_access(access_right)B_Dict = {'node1': now_sat_name, 'node2': B_Name, 'bw': 20, 'delay': str(int(B_Range[0] / 300)) + 'ms','jitter': '1ms','loss': 0}F_Dict = {'node1': now_sat_name, 'node2': F_Name, 'bw': 20,'delay': str(int(F_Range[0] / 300)) + 'ms', 'jitter': '1ms', 'loss': 0}# L_Dict = {'node1': now_sat_name, 'node2': L_Name, 'bw': 20, 'delay': str(int(L_Range[0] / 300))+'ms', 'jitter': '1ms',# 'loss': 0}# R_Dict = {'node1': now_sat_name, 'node2': R_Name, 'bw': 20, 'delay':str(int(R_Range[0] / 300))+'ms', 'jitter': '1ms',# 'loss': 0}data_list.append(B_Dict)data_list.append(F_Dict)# data_list.append(L_Dict)# data_list.append(R_Dict)elif(now_plane_name == 'MEO_'):numOrbitPlanes = 3numSatsPerPlane = 9B_Name = sat_dic['MEO_' + str(now_plane_num) + '-' + str((now_sat_num + 1) % numSatsPerPlane)].InstanceNameF_Name = sat_dic['MEO_' + str(now_plane_num) + '-' + str((now_sat_num - 1) % numSatsPerPlane)].InstanceName# L_Name = sat_dic['MEO_' + str((now_plane_num - 1) % numOrbitPlanes) + '-' + str(now_sat_num)].InstanceName# R_Name = sat_dic['MEO_' + str((now_plane_num + 1) % numOrbitPlanes) + '-' + str(now_sat_num)].InstanceNameaccess_backward = now_sat_transmitter.GetAccessToObject(Get_sat_receiver(sat_dic['MEO_' + str(now_plane_num) + '-' + str((now_sat_num + 1) % numSatsPerPlane)]))# 与前面的卫星的接收机相连access_forward = now_sat_transmitter.GetAccessToObject(Get_sat_receiver(sat_dic['MEO_' + str(now_plane_num) + '-' + str((now_sat_num - 1) % numSatsPerPlane)]))# 与左面的卫星的接收机相连# access_left = now_sat_transmitter.GetAccessToObject(# Get_sat_receiver(sat_dic['MEO_' + str((now_plane_num - 1) % numOrbitPlanes) + '-' + str(now_sat_num)]))# 与右面的卫星的接收机相连# access_right = now_sat_transmitter.GetAccessToObject(# Get_sat_receiver(sat_dic['MEO_' + str((now_plane_num + 1) % numOrbitPlanes) + '-' + str(now_sat_num)]))B_Range = Compute_access(access_backward)F_Range = Compute_access(access_forward)# L_Range = Compute_access(access_left)# R_Range = Compute_access(access_right)B_Dict = {'meo1': now_sat_name, 'meo2': B_Name, 'bw': 20, 'delay': str(int(B_Range[0] / 300)) + 'ms','jitter': '1ms','loss': 0}F_Dict = {'meo1': now_sat_name, 'meo2': F_Name, 'bw': 20,'delay': str(int(F_Range[0] / 300)) + 'ms', 'jitter': '1ms', 'loss': 0}# L_Dict = {'meo1': now_sat_name, 'meo2': L_Name, 'bw': 20, 'delay': str(int(L_Range[0] / 300))+'ms', 'jitter': '1ms',# 'loss': 0}# R_Dict = {'meo1': now_sat_name, 'meo2': R_Name, 'bw': 20, 'delay':str(int(R_Range[0] / 300))+'ms', 'jitter': '1ms',# 'loss': 0}data_list.append(B_Dict)data_list.append(F_Dict)# data_list.append(L_Dict)# data_list.append(R_Dict)elif (now_plane_name == 'GEO_'):numOrbitPlanes = 3numSatsPerPlane = 1
SDN
在SDN部分的研究则相当的广泛了,之前给到的参考资料中可以提供很多的借鉴,后续有时间的话会出一下自己对于RYU控制器的理解以及一些相关功能的实现。基础的知识也就不做太多介绍了。
这里主要分享一下STK与Mininet进行连接以及json数据传输:
大体思路就是利用Falsk将STK的卫星拓扑参数传递给Mininet,Mininet通过读取的轨道参数进行交换机与控制器的构建。以下的代码仅供参考,根据实际情况进行修改即可。
if __name__ == "__main__":setLogLevel("info")OVSKernelSwitch.setup() //开启一个网络intfName_1 = "eth2" //将虚拟机eth2赋值给为变量intfName_1intfName_3 = "eth3"info("****checking****", intfName_1, '\n')checkIntf(intfName_1) //检查是否可用info("****checking****", intfName_3, '\n')checkIntf(intfName_3)info("****creating network****\n")net = Mininet(listenPort = 6633) //创建一个Mininet的实例,端口为6633mycontroller = RemoteController("muziController", ip = "192.168.0.1")//创建远程控制器,ip=192.168.0.1,端口是6633。switch_1 = net.addSwitch('s1') //在net里添加交换机s1,mininet中规则为:如果不填充dpid参数,则dpid参数默认取sn的n.即s1的dpid为1。switch_2 = net.addSwitch('s2')switch_3 = net.addSwitch('s3')switch_4 = net.addSwitch('s4')net.controllers = [mycontroller] //将远程控制器添加到网络中net.addLink(switch_1, switch_2, 2, 1)# node1, node2, port1, port2net.addLink(switch_2, switch_3, 2, 1)//将s2的2端口跟s3的1端口连接起来。(物理连接)net.addLink(switch_1, switch_4, 3, 1)//需要注意的是,以上连接的链路是一个环形的链路,在没有解决风暴的情况下,会出问题。info("*****Adding hardware interface ", intfName_1, "to switch:" ,switch_1.name, '\n')info("*****Adding hardware interface ", intfName_3, "to switch:" ,switch_3.name, '\n')_intf_1 = Intf(intfName_1, node = switch_1, port = 1)//将intfName_1和s1的端口1相连,形成一个接口_intf_1_intf_3 = Intf(intfName_3, node = switch_3, port = 2)net.addLink(switch_4, switch_3, 2, 3)//为什么放在这里呢?因为mininet中允许的端口分配方式是从小到大分配,所以,s3的3端口的配置应该放在s3的2端口之后,虽然难看,但是必须这么做,当然你也可以从新分配端口,只要保证端口是从小到大分配就好了。info("Node: you may need to reconfigure the interfaces for the Mininet hosts:\n", net.hosts, '\n')net.start() //启动netCLI(net) //等待键入命令net.stop() //关闭net
# mininet/mininet/custom/modify_Link.py
from mininet.net import Mininet
from typing import Dict
import time//对于当前node_n_m 得到node_(n+1)_(m+1)
def get_next(n, m, n_max, m_max):n_ = (n+1)%n_maxm_ = (m+1)%m_maxreturn n_, m_//修正Link,用于动态星体时需要修改链路情况时使用
def modifyLink(net:Mininet, node1:str, node2:str, params1:Dict, params2:Dict=None):"""利用params1和params2设置属性连接node1和node2的连接的属性,params1控制node1对应的intfparams2控制node2对应的intf,若缺省则通params1参考 mininet.link.TCIntf.config()params1和params2的键值参考下面for all Intf:mac=None, ip=None, ifconfig=None,up=Trueonly for TCIntf:bw: bandwidth in b/s (e.g. '10m')delay: transmit delay (e.g. '1ms' )jitter: jitter (e.g. '1ms')loss: loss (e.g. '1%' )gro: enable GRO (False)txo: enable transmit checksum offload (True)rxo: enable receive checksum offload (True)speedup: experimental switch-side bw optionuse_hfsc: use HFSC schedulinguse_tbf: use TBF schedulinglatency_ms: TBF latency parameterenable_ecn: enable ECN (False)enable_red: enable RED (False)max_queue_size: queue limit parameter for netem"""h1 = net.getNodeByName( node1 )h2 = net.getNodeByName( node2 )links = h1.connectionsTo(h2)srcIntf = links[0][0] # todo 判断有没有写错dstIntf = links[0][1]if not params2:#* 如果只修改node1,设置params2为非空字典,且不包含上面提到的参数params2 = params1srcIntf.config(**params1)dstIntf.config(**params2)def modifyNode(net:Mininet, node1:str, node2:str, params1:Dict):"""modify intf of node1 that is linked to node2parameters are in modifyLink()for all Intf:mac=None, ip=None, ifconfig=None,up=True"""modifyLink(net, node1, node2, params1, params2=None)//设置ip_table
def set_ip_table(net, node1, node2):h1 = net.getNodeByName( node1 )h2 = net.getNodeByName( node2 )links = h1.connectionsTo(h2)Intf1 = links[0][0]Intf2 = links[0][1]ip1 = Intf1.IP()ip2 = Intf2.IP()name1 = Intf1.namename2 = Intf2.nameh1.cmd(f'ip r del 10.0.0.0/8 dev {name1}')# time.sleep(0.5)command = f'ip r add {ip2}/32 dev {name1} src {ip1}'h1.cmd(command)# time.sleep(0.5)print(f'{node1}--->{command}')h2.cmd(f'ip r del 10.0.0.0/8 dev {name2}')# time.sleep(0.5)command = f'ip r add {ip1}/32 dev {name2} src {ip2}'h2.cmd(command)print(f'{node2}--->{command}')
其中config文件:
```python
n = 5
m = 5# 同轨道默认参数
bw = 100
delay = '5ms'
jitter = '1ms'
loss = 0# 与中继卫星默认参数
mid_bw = 100
mid_delay = '80ms'
mid_jitter = '5ms'
mid_loss = 0
对于SDN主要的也是两块:一是利用Mininet进行拓扑的创建,二是在自己选择的控制器上进行相关功能的设计与实现。
这篇关于SDSN:基于SDN的卫星网络的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!