iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 13
0
自我挑戰組

Cloud/SDN/SFC...菜鳥的學習筆記系列 第 13

Day13 菜鳥的SFC-簡易SFC範例與介紹

今天會有簡易的SFC(Service Function Chain)範例,也會簡單的介紹SFC是什麼。

SFC介紹

SFC(Service Function Chain),指的是一個數據流需要通過多個網絡服務設備,而這多個網路服務設備可以做一些像是防火牆、IDS/IPS等等防護措施。

SFC程式範例

關於pom的部分我就不多介紹了,後面會放github,只單純紀錄function的部分。

AppComponent.java

主要部分為activie()以及deactivate()部分,我將SFC部分做一個class,所以這邊只有做創建以及刪除部分。另外要注意的便是getAppId部分,這裡的ID為Pom內的onos.app.name值。

@Activate
    protected void activate() {
        log.info("Started============================");
        appId = coreService.getAppId("test123"); //equal to the name shown in pom.xml file

         // app id
         mSFCWorking = new SFCWorking(flowRuleService, appId, hostService,
                 deviceService, topologyService, groupService, meterService, meterStore,packetService);
         // add packet processor
         packetService.addProcessor(mSFCWorking, PacketProcessor.director(3));
         packetService.requestPackets(DefaultTrafficSelector.builder()
                 .matchEthType(Ethernet.TYPE_IPV4).build(), PacketPriority.REACTIVE, appId, Optional.empty());

    }

    /**
     * Deactivates the processor by removing it.
     */

    @Deactivate
    protected void deactivate() {
        log.info("Stopped");
        for (GroupDescription description : descriptionArrayList) {
            log.info("remove {} ", description);
            groupService.removeGroup(description.deviceId(), description.appCookie(), appId);
        }
        flowRuleService.removeFlowRulesById(AppComponent.appId);
        packetService.removeProcessor(mSFCWorking);
    }

  CoreService: 控制器的核心系統溝通的功能。
FlowRuleService: 將Flow規則部署到環境中,也可以獲得當前的規則訊息。
PacketService:能獲取Data Plane的封包與直接發送封包到目標port。
packetService:對封包通道做設定。

SFCWorking.java

在這次的範例中,我將ip寫為固定的,也只有一條chain,測試方式也只有使用ping去做測試,因此看到這發現不是需要的可以跳過了。

這裡主要部分為
initMacTable:將一般switch上紀錄mac表實作出來,macTables變數會將switch上的來源的mac與來源port記錄起來。
actLikeSwitch:將封包送到目標port,並且建立新的Flow規則。
runSFC:設定SFC規則,這裡的規則優先權會大於剛剛建立的,因此會跑這邊的規則。

#process會再有封包時就會開始執行
 @Override
    public void process(PacketContext packetContext) {
        log.info("------------------------------------------------------");
        initMacTable(packetContext.inPacket().receivedFrom());
        //registerMeter這部分可以限制傳輸速度,不過由於只是測試SFC,因此註解。
        // registerMeter(packetContext);
        actLikeSwitchforSFC(packetContext);
        runSFC(packetContext);
        // processSFC(packetContext);
    }

actLikeSwitchforSFC部分,我會建立一個簡單的轉發規則,其規則的優先度為10,如果都沒有run這個規則,5秒後便會消失,這單純透過mac以及目的地port去做轉發。

private void actLikeSwitchforSFC(PacketContext packetContext) {
        Ethernet ethernet = packetContext.inPacket().parsed();
        log.info("actLikeSwitchforSFC----------------" + ethernet.getEtherType());

        short type = ethernet.getEtherType();

        if (type != Ethernet.TYPE_IPV4 && type != Ethernet.TYPE_ARP) {
            return;
        }
        ConnectPoint connectPoint = packetContext.inPacket().receivedFrom();
        Map<MacAddress, PortNumber> macTable = macTables.get(connectPoint.deviceId());
        MacAddress srcMac = ethernet.getSourceMAC();

        MacAddress dstMac = ethernet.getDestinationMAC();
        macTable.put(srcMac, connectPoint.port());
        PortNumber outPort = macTable.get(dstMac);

        if (outPort != null) {
            if (type == Ethernet.TYPE_IPV4) {
                IPv4 iPv4 = (IPv4) ethernet.getPayload();

                TrafficSelector trafficSelector = DefaultTrafficSelector.builder()
                        .matchEthSrc(srcMac)
                        .matchEthDst(dstMac)
                        .build();
                createFlowRule(trafficSelector,
                        createTrafficTreatment(null, outPort),
                        connectPoint.deviceId());

            } else {
                packetContext.treatmentBuilder().setOutput(outPort);
                packetContext.send();
            }
        } else {
            actLikeHub(packetContext);
        }
    }
private int Temporary = 5;
private void createFlowRule(TrafficSelector trafficSelector, TrafficTreatment trafficTreatment, DeviceId deviceId) {
        FlowRule flowRule = DefaultFlowRule.builder()
                .fromApp(appId)
                .withSelector(trafficSelector)
                .withTreatment(trafficTreatment)
                .forDevice(deviceId)
                .withPriority(10)
                .makeTemporary(Temporary)
                .build();

        flowRuleService.applyFlowRules(flowRule);
    }

runSFC部分,我會重新建立一個SFC的規則,其優先度為50,由於高於剛剛所建立的規則,因此若有通,則會跑這個規則。

private void runSFC(PacketContext packetContext) {
        if (packetContext.inPacket().parsed().getEtherType() != Ethernet.TYPE_IPV4) return;
        
        ArrayList<String> ipArrayListforReturnRoute = new ArrayList<>(ipArrayList);
        Collections.reverse(ipArrayListforReturnRoute);


        addTag(flowRuleService, packetContext, ipArrayList, false);
    

    }
private void addTag(FlowRuleService flowRuleService, PacketContext packetContext, ArrayList<String> ipArrayListforAddTag, boolean isReverse) {
        new Thread(() -> {
            Ethernet ethernet = packetContext.inPacket().parsed();
            IPv4 iPv4 = (IPv4) ethernet.getPayload();
            int sfId = 0;
            log.info("ipArrayListforAddTag:"+ipArrayListforAddTag);
            for (int position = 0; position < ipArrayListforAddTag.size() - 1; position++) {
                String currentIp = ipArrayListforAddTag.get(position);
                String nextIp = ipArrayListforAddTag.get(position + 1);
                MplsLabel mplsLabel;
                MacAddress ethDst;
                IpPrefix iPDst;
                if (isReverse) {
                    mplsLabel = MplsLabel.mplsLabel(1048575 - sfId);
                    ethDst = ethernet.getSourceMAC();
                    IpAddress dstIpAddress = IpAddress.valueOf(iPv4.getDestinationAddress());
                    iPDst = dstIpAddress.toIpPrefix();
                } else {
                    mplsLabel = MplsLabel.mplsLabel(sfId);
                    ethDst = ethernet.getDestinationMAC();
                    IpAddress dstIpAddress = IpAddress.valueOf(iPv4.getDestinationAddress());
                    iPDst = dstIpAddress.toIpPrefix();
                }
                //currentIpAddress
                IpAddress ipAddress = IpAddress.valueOf(currentIp);

                TrafficTreatment trafficTreatment = DefaultTrafficTreatment.builder()
                        .pushMpls()
                        .setMpls(mplsLabel)
                        .transition(1)
                        .build();


                FlowRule flowRule = DefaultFlowRule.builder()
                        .withSelector(DefaultTrafficSelector.builder()
                                .matchEthType(Ethernet.TYPE_IPV4)
                                .matchEthDst(ethDst)
                                .matchEthSrc(sfcList.get(ipAddress))
                                .matchIPDst(iPDst)
                                .build())
                        .withTreatment(trafficTreatment)
                        .forDevice(packetContext.inPacket().receivedFrom().deviceId())
                        .fromApp(AppComponent.appId)
                        .makeTemporary(Temporary)
                        .withPriority(50)
                        .forTable(0)
                        .build();
                log.info("-----addTagaddTagaddTag------" + flowRule.toString());
                flowRuleService.applyFlowRules(flowRule);

                processSfcFlowRule(packetContext, IpAddress.valueOf(currentIp), IpAddress.valueOf(nextIp), mplsLabel, isReverse, sfId);
                sfId++;

            }
        }).start();
    }

規則檢查

將app放入onos中之後執行mininet指令。

注意要將openFlow打開

sudo mn --controller=remote,ip=<control ip> --mac --topo=single,3 --switch ovsk,protocols=OpenFlow13

執行前置

將中介部分(也就是h2)開放傳封包到其他機器上的功能。

h2 cat /proc/sys/net/ipv4/ip_forward
0 #表示沒開,反之1表示有
h2 echo 1 > /proc/sys/net/ipv4/ip_forward

測試規則有沒有成功

在mininet內輸入(如果沒ping通請確認程式或是看ONOS log看看有沒有找到h1~h3三個裝置的mac,如果沒有,有機會要刪除onos server再重開,這我有遇到過。)

h1 ping h3

到onos看規則是否有成立(會先看到優先度為10的,之後會生成50的,過一段時間50的如果有留著代表有成功,此處只有h1->h2->h3,h3->h1),所以會注意到,來源為01目的地為03的10優先度規則會消失。

到這裡表示簡單的SFC功能完成了,此處只有簡單的ping去做驗證,通過查看SDN內的規則來做確認。
git部分
ps:git clone的時候記得把target部分刪除,這是build才會出來的。


上一篇
Day12 菜鳥的ONOS紀錄-ONOS使用以及ONOS project介紹
下一篇
Day14 菜鳥的SFC-使用API方式建立SFC
系列文
Cloud/SDN/SFC...菜鳥的學習筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言