CC2538之TinyOS例程实验:9-Ppprouter边界路由实验

14 篇文章 1 订阅
11 篇文章 1 订阅

前面我们已经打下了BLIP+RPL的基础,本次例程将全部使用 并添加UART的pppd拨号实现边界路由器;这个例程是核心中的核心;使用它我们可以查看网络路由表而不是再只是通过抓包来自己分析;使用它访问其他的zigbee节点,如下一篇带来的实验CoAPServer;


例程目录:tinyos-main-release_tinyos_2_1_2\apps\cc2538_Test\PppRouter

Makefile文件:前面的介绍大家应该已经清楚了写法,现在开始省略


PppRouterC.nc文件:

#include <iprouting.h>

#include "ppp.h"

configuration PppRouterC {
} implementation {
  components PppRouterP;

  components MainC;
  PppRouterP.Boot -> MainC;

  components LedsC as LedsC;
  PppRouterP.Leds -> LedsC;

  components PppDaemonC;
  PppRouterP.PppControl -> PppDaemonC;

  components PppIpv6C;
  PppDaemonC.PppProtocol[PppIpv6C.ControlProtocol] -> PppIpv6C.PppControlProtocol;
  PppDaemonC.PppProtocol[PppIpv6C.Protocol] -> PppIpv6C.PppProtocol;
  PppIpv6C.Ppp -> PppDaemonC;
  PppIpv6C.LowerLcpAutomaton -> PppDaemonC;

  PppRouterP.Ipv6LcpAutomaton -> PppIpv6C;
  PppRouterP.PppIpv6 -> PppIpv6C;
  PppRouterP.Ppp -> PppDaemonC;

#if defined(PLATFORM_TELOSB) || defined(PLATFORM_EPIC)
  components PlatformHdlcUartC as HdlcUartC;
#else
  components DefaultHdlcUartC as HdlcUartC;
#endif
  PppDaemonC.HdlcUart -> HdlcUartC;
  PppDaemonC.UartControl -> HdlcUartC;

  // SDH : don't bother including the PppPrintfC by default
  // components PppPrintfC, PppC;;
  // PppPrintfC.Ppp -> PppDaemonC;
  // PppDaemonC.PppProtocol[PppPrintfC.Protocol] -> PppPrintfC;
  // PppPrintfC.Ppp -> PppC;

  components IPStackC, IPForwardingEngineP, IPPacketC;
  IPForwardingEngineP.IPForward[ROUTE_IFACE_PPP] -> PppRouterP.IPForward;
  PppRouterP.IPControl -> IPStackC;
  PppRouterP.ForwardingTable -> IPStackC;
  PppRouterP.IPPacket -> IPPacketC;

#ifdef RPL_ROUTING
  components RPLRoutingC, RplBorderRouterP;
  PppRouterP.RootControl -> RPLRoutingC;
  RplBorderRouterP.ForwardingEvents -> IPStackC.ForwardingEvents[ROUTE_IFACE_PPP];
  RplBorderRouterP.IPPacket -> IPPacketC;
#endif

  // UDP shell on port 2000
  components UDPShellC;

  // prints the routing table
   components RouteCmdC;

#ifdef IN6_PREFIX
  components StaticIPAddressTosIdC; // Use TOS_NODE_ID in address
  //components StaticIPAddressC; // Use LocalIeee154 in address
#else
  components Dhcp6C;
  components Dhcp6ClientC;
  PppRouterP.Dhcp6Info -> Dhcp6ClientC;
#endif
}

 注意 components UDPShellC;
         components RouteCmdC;这两个组件,自行去查看底层代码,原来测试命令中的route,heip等是他们定义的,参考他们的写法自己可以定义其他命令,如温度等

PppRouterP.nc文件:

 <span style="font-family: Arial, Helvetica, sans-serif;">/*********************************************************************************************************************************************************</span>
 *实验7----zigbee 边界路由实验
 *节点需求数 >= 2
 *编译命令make cc2538cb blip id.xx (xx为1~65533)
 *测试命令:
 *1,sudo /usr/bin/pppd-hack/sbin/pppd debug passive noauth nodetach 115200 /dev/ttyUSB0 nocrtscts nocdtrcts lcp-echo-interval 0 noccp noip ipv6 ::23,::24 连接边界路由
 *2,新打开shell,执行sudo ifconfig ppp0 add fec0::100/64
 *3,3.1和3.2为两种测试方法,采取一种即可 
 * 3.1执行nc6 -u fec0::1 2000
 *       route
 *       ping6 ff02::xx(xx为1~65533,且为烧写的测试节点号
 * 3.2
 *       ping6 ff02::xx(xx为1~65533,且为烧写的测试节点号
 * 也可以参考\apps\cc2538_Test\PppRouter下的README.blip进行测试,但是注意第一步命令pppd的区别
 * 更多命令支持请参考tinyos-main-release_tinyos_2_1_2\tos\lib\net\blip\shell的UDPShellP.nc文件,如help等,也可以自己添加入传感器等等
 ********************************************************************************************************************************************************/

#include <stdio.h>
#include <lib6lowpan/ip.h>
#include <lib6lowpan/nwbyte.h>
#include <lib6lowpan/ip_malloc.h>
#include <dhcp6.h>

#include "pppipv6.h"
#include "blip_printf.h"

module PppRouterP {
  provides { 
    interface IPForward;
  }
  uses {
    interface Boot;
    interface Leds;
    interface SplitControl as IPControl;
    interface SplitControl as PppControl;
    interface LcpAutomaton as Ipv6LcpAutomaton;
    interface PppIpv6;
    interface Ppp;

    interface ForwardingTable;
    interface RootControl;
    interface Dhcp6Info;
    interface IPPacket;
  }
  
} implementation {

  event void PppIpv6.linkUp() {}
  event void PppIpv6.linkDown() {}

  event void Ipv6LcpAutomaton.transitionCompleted (LcpAutomatonState_e state) { }
  event void Ipv6LcpAutomaton.thisLayerUp () { }
  event void Ipv6LcpAutomaton.thisLayerDown () { }
  event void Ipv6LcpAutomaton.thisLayerStarted () { }
  event void Ipv6LcpAutomaton.thisLayerFinished () { }

  event void PppControl.startDone (error_t error) {  }
  event void PppControl.stopDone (error_t error) { }

  event void IPControl.startDone (error_t error) {
    struct in6_addr dhcp6_group;

    // add a route to the dhcp group on PPP, not the radio (which is the default)
    inet_pton6(DH6ADDR_ALLAGENT, &dhcp6_group);
    call ForwardingTable.addRoute(dhcp6_group.s6_addr, 128, NULL, ROUTE_IFACE_PPP);

    // add a default route through the PPP link
    call ForwardingTable.addRoute(NULL, 0, NULL, ROUTE_IFACE_PPP);
  }
  event void IPControl.stopDone (error_t error) { }

  event void Boot.booted() {
    error_t rc;

#ifndef PRINTFUART_ENABLED
    rc = call Ipv6LcpAutomaton.open();
    rc = call PppControl.start();
#endif
#ifdef RPL_ROUTING
    call RootControl.setRoot();
#endif
#ifndef IN6_PREFIX
    call Dhcp6Info.useUnicast(FALSE);
#endif

    call IPControl.start();
  }

  event error_t PppIpv6.receive(const uint8_t* data,
                                unsigned int len) {
    struct ip6_hdr *iph = (struct ip6_hdr *)data;
    void *payload = (iph + 1);
    call Leds.led0Toggle();
    signal IPForward.recv(iph, payload, NULL);
    return SUCCESS;
  }

  command error_t IPForward.send(struct in6_addr *next_hop,
                                 struct ip6_packet *msg,
                                 void *data) {
    size_t len = iov_len(msg->ip6_data) + sizeof(struct ip6_hdr);
    error_t rc;
    frame_key_t key;
    const uint8_t* fpe;
    uint8_t* fp;
    
    if (!call PppIpv6.linkIsUp()) 
      return EOFF;

    // get an output frame
    fp = call Ppp.getOutputFrame(PppProtocol_Ipv6, &fpe, FALSE, &key);
    if ((! fp) || ((fpe - fp) < len)) {
      if (fp) {
	call Ppp.releaseOutputFrame(key);
      }
      call Leds.led2Toggle();
      return ENOMEM;
    }

    // copy the header and body into the frame
    memcpy(fp, &msg->ip6_hdr, sizeof(struct ip6_hdr));
    iov_read(msg->ip6_data, 0, len, fp + sizeof(struct ip6_hdr));
    rc = call Ppp.fixOutputFrameLength(key, fp + len);
    if (SUCCESS == rc) {
      rc = call Ppp.sendOutputFrame(key);
    }

    call Leds.led1Toggle();

    return rc;
  }

  event void Ppp.outputFrameTransmitted (frame_key_t key,
                                         error_t err) { }

}
阅读代码可以发现PRINTFUART_ENABLED不要开启,不然ppp模块是编译去除的;

源码是pppd的例程部分和发送数据接收数据的处理

RplBorderRouterP.nc文件:

#include <lib6lowpan/ip.h>
#include <iprouting.h>
#include <RPL.h>

module RplBorderRouterP {
  uses {
    interface ForwardingEvents;
    interface IPPacket;
  }
} implementation {

  event bool ForwardingEvents.initiate(struct ip6_packet *pkt,
                                       struct in6_addr *next_hop) {
    return TRUE;
  }

  event bool ForwardingEvents.approve(struct ip6_packet *pkt,
                                      struct in6_addr *next_hop) {
    int off;
    uint8_t nxt = IPV6_HOP;
    if (pkt->ip6_inputif == ROUTE_IFACE_PPP)
      return FALSE;

    /* remove any RPL options in the hop-by-hop header by converting
       them to a PadN option */
    off = call IPPacket.findHeader(pkt->ip6_data, pkt->ip6_hdr.ip6_nxt, &nxt);
    if (off < 0) return TRUE;
    call IPPacket.delTLV(pkt->ip6_data, off, RPL_HBH_RANK_TYPE);

    return TRUE;
  }

  event void ForwardingEvents.linkResult(struct in6_addr *dest, struct send_info *info) {

  }
}

这个components是缺省写法,大家以后可以学习他的写法来偷懒,没有编写configuration和interface文件;

文件中的事件是网络路由事件;


本例程带有测试视频;截图神马的就忽略了,其中的pppd命令使用自己安装的pppd_hack的原因是因为当主机是XP的时候,虚拟机使用pppd命令,出现假死,当主机是WIN8的时候,虚拟机同样的使用pppd时正常的;于是我干脆自己安装了pppd_hack,这样主机XP或WIN8就都可以了;pppd_hack虚拟机已经安装好,参考的lab11的blip测试网页安装,百度网盘也有安装包;


可以先烧写一个Ppprouter节点连接PC,按照视频启动pppd连接,可以输入路由表查看命令,查看本机路由;

再准备一个UDPECHO节点,编译烧写,再在虚拟机查看Ppprouter节点路由表或者登陆UDPECHO节点,查看一下它的路由表;


当然你也可以先跳过UDPECHO;我自己就基本不测试他,可以pppd连接后,直接跳过测试,进入下一部CoAPServer节点实验实行ping6测试,coap的led控制!



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值