SDSN:基于SDN的卫星网络

SDSN:基于SDN的卫星网络

前段时间一直在做跟SDN与卫星网络相关的毕设,学习了很多东西也走了很多弯路,所以想分享一下自己的学习过程,并且对相关的知识做一个总结。

有很多同学问我,所以放一下我自己关于这个项目的github链接:

https://github.com/YangShine-GenZ/SDN_Satellite.git

思路框架

相关知识获取:

关于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

研究过程

完成整个研究任务需要大致了解一下几个方面:

  1. 卫星网络是如何构建的,他有怎么样的参数,轨道是什么样的,卫星是如何运动的,星体模型是什么样的?例如一个常见的铱星(Iridium)系统。
  2. SDN是一个什么样的概念,他的应用场景和关键技术是怎么样的?他在卫星网络中又是如何被使用的?
  3. SDN控制器与交换器各个是什么样的概念,是如何实现如何应用的。OpenFlow协议又是什么概念?
  4. 在SDSN(Sat+SDN)的场景中,卫星与SDN是如何相互配合相互实现的?目前的研究领域和研究目标有哪些?技术难点和应用创新点有哪些?
  5. 针对上述知识,如何在技术上进行仿真与实现?

天体网络架构

整体工作可以大致切分为两块:系统架构(实验环境(当然也有可能是研究内容))+ 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坐标系轨道升交点赤经

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L09SlS7n-1687513200531)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/b52c343b-649d-4f99-bbc9-cbcfc5f2f0d7/Untitled.png)]

2)设定种子卫星;本文以2019.05.27日根数分析结果,设定种子卫星历元及根数为:27 May 2019 06:14:00.000 UTC、半长轴6928.137(高度550km)、升交点赤经160°、轨道倾角53°、偏心率0°、其他轨道参数为0。为卫星添加传感器(Sensor),设定圆锥半角为44.85°,为后续覆盖分析做准备。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K01fgAKJ-1687513200532)(https://s3-us-west-2.amazonaws.com/secure.notion-static.com/408da770-148c-4627-aa5f-a412622c519c/Untitled.png)]

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 tqdm

startTime = 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 Engine
    print("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 object
    stkRoot = CreateObject('AgStkObjects11.AgStkObjectRoot')

else:
    # Launch GUI
    print("Launching STK...")
    if not Read_Scenario:
        uiApp = CreateObject("STK11.Application")
    else:
        uiApp = GetActiveObject("STK11.Application")
    uiApp.Visible = True
    uiApp.UserControl = True

    # Get root object
    stkRoot = 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 object
    print("--- 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 Satellites
    for orbitPlaneNum in range(numOrbitPlanes):  # RAAN in degrees
        print("---create sat on orbitPlane {a} ---".format(a=orbitPlaneNum))

        for satNum in range(numSatsPerPlane):  # trueAnomaly in degrees
            # Insert satellite
            satellite = scenario.Children.New(STKObjects.eSatellite, f"{name}{orbitPlaneNum}-{satNum}")
            satellite2 = satellite.QueryInterface(STKObjects.IAgSatellite)

            # Select Propagator
            satellite2.SetPropagatorType(STKObjects.ePropagatorTwoBody)

            # Set initial state
            twoBodyPropagator = 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 = 0

            keplarian.Orientation.Inclination = int(Inclination)  # degrees 倾角
            keplarian.Orientation.ArgOfPerigee = 0  # degrees 近地点
            keplarian.Orientation.AscNodeType = STKObjects.eAscNodeRAAN
            RAAN = 360 / numOrbitPlanes * orbitPlaneNum
            keplarian.Orientation.AscNode.QueryInterface(STKObjects.IAgOrientationAscNodeRAAN).Value = RAAN  # degrees

            keplarian.LocationType = STKObjects.eLocationTrueAnomaly
            trueAnomaly = 360 / numSatsPerPlane * satNum
            keplarian.Location.QueryInterface(STKObjects.IAgClassicalLocationTrueAnomaly).Value = trueAnomaly

            # Propagate
            satellite2.Propagator.QueryInterface(STKObjects.IAgVePropagatorTwoBody).InitialState.Representation.Assign(
                keplarian)
            satellite2.Propagator.QueryInterface(STKObjects.IAgVePropagatorTwoBody).Propagate()

            # Add to constellation object
            constellation2.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 receiver
        transmitter = 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.Model
    txModel = txModel.QueryInterface(STKObjects.IAgTransmitterModelSimple)
    txModel.Frequency = frequency  # GHz range:10.7-12.7GHz
    txModel.EIRP = EIRP  # dBW
    txModel.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.Model
    recModel = recModel.QueryInterface(STKObjects.IAgReceiverModelSimple)
    recModel.AutoTrackFrequency = False
    recModel.Frequency = frequency  # GHz range:10.7-12.7GHz
    recModel.GOverT = GT  # dB/K
    return 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 receiver2


def 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 Range


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.InstanceName
        now_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)].InstanceName
        F_Name = sat_dic['node_' + str(now_plane_num) + '-' + str((now_sat_num - 1) % 10)].InstanceName
        L_Name = sat_dic['node_' + str((now_plane_num - 1) % 10) + '-' + str(now_sat_num)].InstanceName
        R_Name = sat_dic['node_' + str((now_plane_num + 1) % 10) + '-' + str(now_sat_num)].InstanceName
        access_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.InstanceName
        now_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.Graphics
        graphics.SetAttributesType(1)  # eAttributesBasic
        attributes = graphics.Attributes
        attributes_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 = 255
        elif now_sat_name[2] == 'B':
            color = 42495
        elif now_sat_name[2] == 'C':
            color = 16436871
        attributes_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.InstanceName
        tmpparam={'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 C
    sat_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+=600
    print(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.InstanceName
        print(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 = 6
            numSatsPerPlane = 12
            B_Name = sat_dic['LEO_' + str(now_plane_num) + '-' + str((now_sat_num + 1) % numSatsPerPlane)].InstanceName
            F_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)].InstanceName
            access_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 = 3
            numSatsPerPlane = 9
            B_Name = sat_dic['MEO_' + str(now_plane_num) + '-' + str((now_sat_num + 1) % numSatsPerPlane)].InstanceName
            F_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)].InstanceName
            access_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 = 3
            numSatsPerPlane = 1

SDN

在SDN部分的研究则相当的广泛了,之前给到的参考资料中可以提供很多的借鉴,后续有时间的话会出一下自己对于RYU控制器的理解以及一些相关功能的实现。基础的知识也就不做太多介绍了。
这里主要分享一下STK与Mininet进行连接以及json数据传输:
大体思路就是利用Falsk将STK的卫星拓扑参数传递给Mininet,Mininet通过读取的轨道参数进行交换机与控制器的构建。以下的代码仅供参考,根据实际情况进行修改即可。

if __name__ == "__main__":
    setLogLevel("info")
    OVSKernelSwitch.setup() //开启一个网络
    intfName_1 = "eth2"     //将虚拟机eth2赋值给为变量intfName_1
    intfName_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的实例,端口为6633

    mycontroller = 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()  //启动net
    CLI(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_max
    m_ = (m+1)%m_max
    return n_, m_

//修正Link,用于动态星体时需要修改链路情况时使用
def modifyLink(net:Mininet, node1:str, node2:str, params1:Dict, params2:Dict=None):
    """

    利用params1和params2设置属性连接node1和node2的连接的属性,
    params1控制node1对应的intf
    params2控制node2对应的intf,若缺省则通params1


    参考 mininet.link.TCIntf.config()


    params1和params2的键值参考下面

    for all Intf:
        mac=None, 
        ip=None, 
        ifconfig=None,
        up=True

    only 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 option
           use_hfsc: use HFSC scheduling
           use_tbf: use TBF scheduling
           latency_ms: TBF latency parameter
           enable_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 = params1
    srcIntf.config(**params1)
    dstIntf.config(**params2)


def modifyNode(net:Mininet, node1:str, node2:str, params1:Dict):
    """
    modify intf of node1 that is linked to node2
    parameters 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.name
    name2 = Intf2.name

    h1.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进行拓扑的创建,二是在自己选择的控制器上进行相关功能的设计与实现。

  • 12
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
要使用 MFC 更改 Access 中的数据,你需要使用 MFC 的数据库类和 ODBC 驱动程序。下面是一个简单的示例,演示如何使用 MFC 对 Access 数据库进行增删改查操作: 1. 首先,在你的 MFC 应用程序中添加一个数据库类。右键单击项目,选择“添加”->“类”,然后选择“数据库”类。 2. 在你的数据库类中添加以下代码,以连接到 Access 数据库: ``` BOOL CMyDatabase::Open() { CString sDriver = _T("Microsoft Access Driver (*.mdb)"); CString sFile = _T("C:\\mydatabase.mdb"); CString sDsn; sDsn.Format(_T("ODBC;DRIVER={%s};DSN='';DBQ=%s"), sDriver, sFile); if (!CDatabase::OpenEx(sDsn, CDatabase::noOdbcDialog)) { return FALSE; } return TRUE; } ``` 其中,sFile 是你的 Access 数据库文件的路径。 3. 添加以下代码,以执行增删改查操作: ``` BOOL CMyDatabase::AddRecord(const CString& sName, const CString& sAddress) { CString strSQL; strSQL.Format(_T("INSERT INTO MyTable (Name, Address) VALUES ('%s', '%s')"), sName, sAddress); try { ExecuteSQL(strSQL); return TRUE; } catch(CDBException* e) { TRACE(_T("Error: %s\n"), e->m_strError); e->Delete(); return FALSE; } } BOOL CMyDatabase::UpdateRecord(int nID, const CString& sName, const CString& sAddress) { CString strSQL; strSQL.Format(_T("UPDATE MyTable SET Name = '%s', Address = '%s' WHERE ID = %d"), sName, sAddress, nID); try { ExecuteSQL(strSQL); return TRUE; } catch(CDBException* e) { TRACE(_T("Error: %s\n"), e->m_strError); e->Delete(); return FALSE; } } BOOL CMyDatabase::DeleteRecord(int nID) { CString strSQL; strSQL.Format(_T("DELETE FROM MyTable WHERE ID = %d"), nID); try { ExecuteSQL(strSQL); return TRUE; } catch(CDBException* e) { TRACE(_T("Error: %s\n"), e->m_strError); e->Delete(); return FALSE; } } BOOL CMyDatabase::GetRecord(int nID, CString& sName, CString& sAddress) { CString strSQL; strSQL.Format(_T("SELECT Name, Address FROM MyTable WHERE ID = %d"), nID); try { CRecordset rs(this); rs.Open(CRecordset::forwardOnly, strSQL); if (rs.GetRecordCount() == 0) { return FALSE; } rs.GetFieldValue(_T("Name"), sName); rs.GetFieldValue(_T("Address"), sAddress); rs.Close(); return TRUE; } catch(CDBException* e) { TRACE(_T("Error: %s\n"), e->m_strError); e->Delete(); return FALSE; } } ``` 其中,MyTable 是你的 Access 数据库中的表名。 4. 调用上述函数,以执行相应的操作。例如: ``` CMyDatabase db; if (db.Open()) { // 添加记录 db.AddRecord(_T("John Doe"), _T("123 Main St.")); // 修改记录 db.UpdateRecord(1, _T("Jane Doe"), _T("456 Elm St.")); // 删除记录 db.DeleteRecord(2); // 获取记录 CString sName, sAddress; if (db.GetRecord(1, sName, sAddress)) { TRACE(_T("Name: %s\nAddress: %s\n"), sName, sAddress); } } db.Close(); ``` 注意,上述代码仅供参考,并且可能需要根据你的实际情况进行修改。此外,还需要确保你的 Access 数据库已正确设置,并且你的 ODBC 驱动程序已正确安装。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值