Internet DRAFT - draft-tian-sdnrg-pnpl

draft-tian-sdnrg-pnpl



 



INTERNET-DRAFT                                                   Y. Tian
Intended Status: Informational               Univ. Sci. & Tech. of China
Expires: December 21, 2018                                              
                                                                        
                                                                        
                                                                        
                                                           July 18, 2018



   Programming Model for Protocol Oblivious Forwarding SDN Networks 
                        draft-tian-sdnrg-pnpl-01


Abstract

   This document presents PNPL, a Software-Defined Networking (SDN)
   programming model for the Protocol Oblivious Forwarding (POF)
   network. POF is an SDN forwarding plane technology proposed by
   Huawei. A POF forwarding element (FE) does no need to understand the
   packet format, and can be programmed to support new forwarding
   protocols. PNPL enables user to define forwarding protocols and
   program the POF SDN network on the centralized control plane with
   algorithmic policies that are expressed with high-level programming
   languages.


Status of this Memo

   This Internet-Draft is submitted to IETF in full conformance with the
   provisions of BCP 78 and BCP 79.

   Internet-Drafts are working documents of the Internet Engineering
   Task Force (IETF), its areas, and its working groups.  Note that
   other groups may also distribute working documents as
   Internet-Drafts.

   Internet-Drafts are draft documents valid for a maximum of six months
   and may be updated, replaced, or obsoleted by other documents at any
   time.  It is inappropriate to use Internet-Drafts as reference
   material or to cite them other than as "work in progress."

   The list of current Internet-Drafts can be accessed at
   http://www.ietf.org/1id-abstracts.html

   The list of Internet-Draft Shadow Directories can be accessed at
   http://www.ietf.org/shadow.html

 


<Author>               Expires December 21, 2018                [Page 1]

INTERNET DRAFT              <Document Title>               July 18, 2018


Copyright and License Notice

   Copyright (c) 2018 IETF Trust and the persons identified as the
   document authors. All rights reserved.

   This document is subject to BCP 78 and the IETF Trust's Legal
   Provisions Relating to IETF Documents
   (http://trustee.ietf.org/license-info) in effect on the date of
   publication of this document. Please review these documents
   carefully, as they describe your rights and restrictions with respect
   to this document. Code Components extracted from this document must
   include Simplified BSD License text as described in Section 4.e of
   the Trust Legal Provisions and are provided without warranty as
   described in the Simplified BSD License.



Table of Contents

   1  Introduction  . . . . . . . . . . . . . . . . . . . . . . . . .  3
     1.1  Terminology . . . . . . . . . . . . . . . . . . . . . . . .  4
   2  Programming Model . . . . . . . . . . . . . . . . . . . . . . .  4
   3  Protocol Specification Language . . . . . . . . . . . . . . . .  5
   4  Programming APIs for Protocol Oblivious Networking Algorithm  .  7
     4.1 Packet Operation API . . . . . . . . . . . . . . . . . . . .  7
     4.2 Net Topology Search API  . . . . . . . . . . . . . . . . . . 12
     4.3 Path Planning API  . . . . . . . . . . . . . . . . . . . . . 15
   5  Tracing Runtime System  . . . . . . . . . . . . . . . . . . . . 16
     5.1  Parse Graph and Parse Graph Instance  . . . . . . . . . . . 16
     5.2  Trace . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
     5.3  Extended Tracing Tree . . . . . . . . . . . . . . . . . . . 16
     5.4  Forwarding Pipeline . . . . . . . . . . . . . . . . . . . . 17
     5.5  Optimization  . . . . . . . . . . . . . . . . . . . . . . . 17
   6  Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
   7 Security Considerations  . . . . . . . . . . . . . . . . . . . . 19
   8 IANA Considerations  . . . . . . . . . . . . . . . . . . . . . . 19
   9 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
   10  References . . . . . . . . . . . . . . . . . . . . . . . . . . 20
     10.1  Normative References . . . . . . . . . . . . . . . . . . . 20
     10.2  Informative References . . . . . . . . . . . . . . . . . . 20
   Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . . 20







 


<Author>               Expires December 21, 2018                [Page 2]

INTERNET DRAFT              <Document Title>               July 18, 2018


1  Introduction

   Software-Defined Networking (SDN)[RFC7149] gives operators
   programmatic control over their networks. In SDN, the control plane
   is physically separate from the forwarding plane, and one control
   plane controls multiple forwarding devices. In SDN, a common, open,
   vendor-agnostic interface between the control plane and the
   forwarding plane, which may contain forwarding devices from different
   hardware and software vendors, is required. OpenFlow is such an
   interface. In OpenFlow, operators express their rules with the
   abstractions that could match packets on a dozen header fields (e.g.,
   MAC addresses, IP addresses, protocol, TCP/UDP port numbers, etc.),
   and specify the corresponding actions (e.g., output, drop,
   encapsulate, etc.). 

   Generally speaking, a packet is composed of multiple protocol headers
   and payload. The protocol headers are parsed and modified by NP
   micro-code or ASIC logic during the forwarding process. The position
   of each protocol field, such as the IPv4 source address, is
   calculated by the code that is preloaded into the devices according
   to protocol format by the device vendor. If one new protocol needs to
   be supported, the code must be modified. This will lead to a long
   deployment cycle for new services based on new protocols.

   The current OpenFlow-based SDN[RFC7426] cannot resolve the
   aforementioned problem. The position of the protocol fields cannot be
   derived from the flow's forwarding instructions. So the position of
   each protocol fields must be calculated by the code, which means the
   code of the devices must be modified for processing new protocol
   headers.

   For this reason, Huawei presents the Protocol Oblivious Forwarding
   (POF) technology. The basic idea is to denote any protocol field, as
   well as the metadata, which is considered as one special protocol
   header that can be configured by the controller, with a triad of
   <type, offset, length>.

   POF also defines a set of protocol oblivious forwarding
   actions/instructions. The actions/instructions can realize the
   functions of all forwarding instructions/actions defined in OpenFlow,
   not only for the existing protocols but also for any new protocols. 

   With the protocol oblivious data plane that are composed of POF
   forwarding devices, a programming model that enable user to program
   such a data plane is required. This memo presents POP, an open, easy-
   to-use, and efficient programming model.

   The memo describes a protocol specification language that enable user
 


<Author>               Expires December 21, 2018                [Page 3]

INTERNET DRAFT              <Document Title>               July 18, 2018


   to specify any network protocol that he intends to program on the POF
   network. Then the programming API that allows user to program the POF
   network is introduced. The memo also contains demonstration
   examples.


1.1  Terminology

   The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
   "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
   document are to be interpreted as described in RFC 2119 [RFC2119].


    Software-Defined Networking (SDN) - A programmable networks approach
    that supports the separation of control and forwarding planes via
    standardized interfaces.

    Forwarding Plane (FP) - The collection of resources across all
    network devices responsible for forwarding traffic.

    Control Plane (CP) - The collection of functions responsible for
    controlling one or more network devices.CP instructs network devices
    with respect to how to process and forward packets.  The control
    plane interacts primarily with the forwarding plane and, to a lesser
    extent, with the operational plane.

    Protocol Oblivious Forwarding (POF) - The protocol that is proposed
    by Huawei to provide a new way to develop SDN.  

2  Programming Model 

    PNPL provides a high-level protocol specification language
    abstraction other than {offset,length} tuples for specifying
    complicated packet formats. With the language, PNPL enables a
    programmer to arbitrarily define network protocols with complicated
    header structures. The BNF normal form of PNPL's protocol
    specification language is shown in section 3.

    PNPL also provides a set of protocol-agnostic programming APIs for
    user to compose network policies. with the APIs, a programmer can
    compose his network policy over the self-defined protocols, without
    worrying the data plane details.The lists of APIs are shown in
    section 4.

    After a programmer specifies the network protocol with header
    specification and describes his network policy, PNPL's tracing
    runtime system takes them as input, handles unparsed packets
    reported from the data plane, and automatically generates forwarding
 


<Author>               Expires December 21, 2018                [Page 4]

INTERNET DRAFT              <Document Title>               July 18, 2018


    pipelines that simultaneously parse packets and enforce programmer's
    network policy. The details of tracing runtime system is shown in
    section 5.

    +------------------------------------------------------------------+
    | +-----------------+ +-------------------------------+            |
    | |Network algorithm| |Protocol Specification Language| User level |
    | +----^------------+ +----^---------^----------------+            |
    +------+----------------+--+---------+-----------------------------+
           |                |  |         |             PNPL controller
    +------+----------------+--+---------+-----------------------------+
    |   +--v--+             |  |         |                             |
    |   |  PG |      +------+  |         |                System level |
    |   +--^--+      |         |         |                             |
    |      |         |         |         |                             |
    |  +---+---------+---------+---------+---+                         |
    |  |+--v--+   +--v--+   +--v--+   +--v--+|                         |
    |  || PGI +---> xTT +---> xTT +---> xTT ||PG:parse graph           |
    |  |+-----+   +--^--+   +--^--+   +--^--+|PGI:parse graph instance |
    |  |             |         |         |   |xTT:extended tracing tree|
    |  |             |         |         |   |FP:forwarding pipeline   |
    |  | Runtime  +--v--+   +--v--+   +--v---+                         |
    |  |          |  FP |   |  FP |   |  FP ||                         |
    |  |          +-----+   +-----+   +------|                         |
    |  +-------------------------------------|                         |
    +--------+---------------------+---------------------+-------------+
             |                     |                     |
             |                     |                     |  Data plane
    +--------v---------------------v---------------------v-------------+
    |                                                                  |
    |                        +------------+                            |
    |                        | POF Switch |                            |
    |  +------------+        +------------+         +------------+     |
    |  | POF Switch |                               | POF Switch |     |
    |  +------------+                               +------------+     |
    +------------------------------------------------------------------+

3  Protocol Specification Language

    Protocol Specification Language is learned from P4. It include a
    number of protocol header definitions and a "start" symbol which
    represent the starting protocol header while parsing. User can
    define the protocol header layer by layer. The BNF normal form of
    Protocol Specification Language is showed as follows.

      Identifier and unsigned number: The "IDENT" represent Identifier.
      "NUMBER" represent unsigned number. "e" represent NULL.
      +------------------------------------------------------------+
 


<Author>               Expires December 21, 2018                [Page 5]

INTERNET DRAFT              <Document Title>               July 18, 2018


      |IDENT ::= [_a-zA-Z][_0-9a|zA-Z]*                            |
      |NUMBER ::= 0[bB][01]+|0[0|7]*|[1-9][0-9]*|0[xX][0-9a-fA-F]+ |
      +------------------------------------------------------------+

      Main program: a number of protocol header definitions and "start"
      symbol.
      +------------------------------------------------------------+
      |program ::= headers start                                   |
      |start ::= "start" IDENT ";"                                 |
      |headers ::= e | header headers | header_decl headers        |
      +------------------------------------------------------------+

      Header definition: Include header name, protocol fields list,
      header length, next-layer selection.
      +------------------------------------------------------------+
      |header ::= "header" IDENT fields length next                |
      |header_decl ::= "header" IDENT ";"                          |
      +------------------------------------------------------------+

      Protocol fields: each field include a binary length. A protocol
      allows at most one field which length is uncertain and mark as
      "*". Meanwhile, it should at the end of the list.
      +------------------------------------------------------------+
      |fields ::= "fields" items                                   |
      |items ::= e | IDENT ":" (NUMBER | "*") ";" items            |
      +------------------------------------------------------------+

      Header length: option, is a expression consists of field name and
      constant. When it's implicit, the protocol fields list can
      calculate header length automatically.
      +------------------------------------------------------------+
      |length ::= e | "length" ":" expr ";"                        |
      +------------------------------------------------------------+

      Expression: follow language specification of C. Operator have
      different priority from high to low. Operator which have the same
      priority cannot bond except bracket.
      +------------------------------------------------------------+
      |expr ::= IDENT | NUMBER |                                   |
      |"(" expr ")" | (bracket)                                    |
      |"~" expr | (NOT)                                            |
      |expr "+" expr | expr "-" expr | (Add/Subtract)              |
      |expr "<>" expr | expr "<>" expr | (shift logical left/right)|
      |expr "&" expr | (AND)                                       |
      |expr "^" expr | (XOR)                                       |
      |expr "|" expr (OR)                                          |
      +------------------------------------------------------------+

 


<Author>               Expires December 21, 2018                [Page 6]

INTERNET DRAFT              <Document Title>               July 18, 2018


      Next-layer selection: according to value of one header field. Each
      case include the value and next-layer header name. Next header
      name can be recursive directly or indirectly. But the header name
      should has been defined or are defined.
      +------------------------------------------------------------+
      |next ::= e | "next" IDENT ";" | "next"                      |
      |"select" "(" IDENT ")" cases                                |
      |cases ::= e | "case" NUMBER ":" IDENT ";" cases             |
      +------------------------------------------------------------+


4  Programming APIs for Protocol Oblivious Networking Algorithm

      Users make use of a series of API to define network algorithm.
      Functionly,those APIs include three parts which named 'Packet
      Operation','Net Topology Search' and 'Path Planing'.

4.1 Packet Operation API

      PNPL supports any kinds of protocol message format that the API
      for message operation doesn't rely on any specific protocol. As
      the following figure,PNPL supplies a 'layer-by-layer progressive'
      method by the concept of network protocol stack that the packet is
      parsed into many layers.

      +---------------------+
      |                     | 
      |       Ethernet      |
      |                     |
      +---------------------+
                 |
                 |
                 |
      +----------v----------+
      |                     | 
      |        VLAN         | 
      |                     | 
      +---------------------+
                 |
                 |
                 |
      +----------v----------+
      |                     |
      |        IPv4         |
      |                     |
      +---------------------+
                 |
                 |
 


<Author>               Expires December 21, 2018                [Page 7]

INTERNET DRAFT              <Document Title>               July 18, 2018


                 |
      +----------v----------+
      |                     |
      |        TCP          |
      |                     |
      +---------------------+
      PNPL supports for the following Packet Operation API:

      apply_PG
      +------------------------------------------------------------+
      |PGI *apply_PG(struct packet *pkt);                          |
      |function::apply a packet to PG and obtain a PGI             |
      |input:                                                      |
      |     pkt                   packet                           |
      |output:                                                     |
      |     packet graph instance of pkt                           |
      +------------------------------------------------------------+
      declare_metadata
      +------------------------------------------------------------+
      |void declare_metadata(PGI *pgi,const char *m_field,int len) |
      |function::Declare a data piece of given length in metadata  |
      |input:                                                      |
      |     pgi                   packet graph instance            |
      |     m_field               name of data piece               |
      |     len                   length of data piece             |
      |output:                                                     |
      |     none                                                   |
      +------------------------------------------------------------+
      read_packet_inport
      +------------------------------------------------------------+
      |int read_packet_inport(PGI *pgi);                           |
      |function::read the enter port of packet                     |
      |input:                                                      |
      |     pgi                   packet graph instance            |
      |output:                                                     |
      |     current packet enter port number of switch             |
      +------------------------------------------------------------+
      read_packet_inswitch
      +------------------------------------------------------------+
      |struct entity *read_packet_inswitch(PGI *pgi);              |
      |function::read the enter switch of packet                   |
      |input:                                                      |
      |     pgi                   packet graph instance            |
      |output:                                                     |
      |     current packet's enter switch number                   |
      +------------------------------------------------------------+
      read_header_type
      +------------------------------------------------------------+
 


<Author>               Expires December 21, 2018                [Page 8]

INTERNET DRAFT              <Document Title>               July 18, 2018


      |const char *read_header_type(PGI *pgi);                     |
      |function::read the name of current header                   |
      |input:                                                      |
      |     pgi                   packet graph instance            |
      |output:                                                     |
      |     current header's name                                  |
      +------------------------------------------------------------+
      read_packet
      +------------------------------------------------------------+
      |value_t read_packet(PGI *pgi, const char *p_field);         |
      |function::read value from a packet field                    |
      |input:                                                      |
      |     pgi                   packet graph instance            |
      |     p_field               field name                       |
      |output                                                      |
      |     value of current p_field                               |
      |                                                            |
      +------------------------------------------------------------+
      test_equal
      +------------------------------------------------------------+
      |bool test_equal(PGI *pgi,const char *p_field,value_t val);  |
      |function::testify if value of field equals to a given value |
      |input:                                                      |
      |     pgi                   packet graph instance            |
      |     p_field               field name                       |
      |     val                   value waiting for test           |
      |output:                                                     |
      |     if p_field value is equal to val,return true;          |
      |     else return false                                      |
      +------------------------------------------------------------+
      search_header
      +------------------------------------------------------------+
      |bool search_header(PGI *pgi,const char *name,               |
      |                   struct list m_fields);                   |
      |function::search and skip to a specified header             |
      |input:                                                      |
      |     pgi                   packet graph instance            |
      |     name                  header name                      |
      |     m_fields              fields in metadata               |
      |output:                                                     |
      |     if the packet contains the header,return true;         |
      |     else return false                                      |
      +------------------------------------------------------------+
      write_metadata
      +------------------------------------------------------------+
      |bool write_metadata(PGI *pgi,const char *m_field,           |
      |                    const char *p_field);                   |
      |function::write value of a packet field to a data piece     |
 


<Author>               Expires December 21, 2018                [Page 9]

INTERNET DRAFT              <Document Title>               July 18, 2018


      |          in metadata                                       |
      |input:                                                      |
      |     pgi                   packet graph instance            |
      |     m_field               field name in metadata           |
      |     p_field               field name in packet             |
      |output:                                                     |
      |     if write success,return true;else return false         |
      +------------------------------------------------------------+
      write_metadata
      +------------------------------------------------------------+
      |bool write_metadata(PGI *pgi,const char *m_field,           |
      |                    value_t val);                           |
      |function::write a given value to a data piece in metadata   |
      |input:                                                      |
      |     pgi                   packet graph instance            |
      |     m_field               field name in metadata           |
      |     val                   value                            |
      |output:                                                     |
      |     if write success,return true;else return false         |
      +------------------------------------------------------------+
      test_equal_metadata
      +------------------------------------------------------------+
      |bool test_equal_metadata(PGI *pgi,const char *m_field,      |
      |                    value_t val);                           |
      |function::testify if value of a data piece in metadata      |
      |          equals to a given value                           |
      |input:                                                      |
      |     pgi                   packet graph instance            |
      |     m_field               field name in metadata           |
      |     val                   value                            |
      |output:                                                     |
      |     if value of m_field equals to val,return true;         |
      |     else return false                                      |
      +------------------------------------------------------------+
      read_payload
      +------------------------------------------------------------+
      |const uint8_t *read_payload(PGI *pgi);                      |
      |function::read a packet's payload                           |
      |input:                                                      |
      |     pgi                   packet graph instance            |
      |output:                                                     |
      |     packet's payload                                       |
      +------------------------------------------------------------+
      add_header
      +------------------------------------------------------------+
      |void add_header(PGI *pgi,const char *name);                 |
      |function::add a header of the given name in header specific-|
      |          ation after the current header, all the fields are|
 


<Author>               Expires December 21, 2018               [Page 10]

INTERNET DRAFT              <Document Title>               July 18, 2018


      |          initialized with'0's, and if the header contains a|
      |          variable-length field, the field is skipped       |
      |input:                                                      |
      |     pgi                   packet graph instance            |
      |     name                  header name                      |
      |output:                                                     |
      |     none                                                   |
      +------------------------------------------------------------+
      mod_packet
      +------------------------------------------------------------+
      |bool mod_packet(PGI *pgi,const char *p_field,               |
      |                const char *m_field);                       |
      |function::modify value of a field in the current header with|
      |          a data piece in metadata                          |
      |input:                                                      |
      |     pgi                   packet graph instance            |
      |     p_field               field name in packet             |
      |     m_field               field name in metadata           |
      |output:                                                     |
      |     if modify success,return true;else return false        |
      +------------------------------------------------------------+
      mod_packet
      +------------------------------------------------------------+
      |bool mod_packet(PGI *pgi,const char *p_field,value_t val);  |
      |function::modify value of a field in the current header with|
      |          a given value                                     |
      |input:                                                      |
      |     pgi                   packet graph instance            |
      |     p_field               field name in packet             |
      |     val                   given value                      |
      |output:                                                     |
      |     if modify success,return true;else return false        |
      +------------------------------------------------------------+
      add_packet
      +------------------------------------------------------------+
      |void add_packet(PGI *pgi,const char *p_field,               |
      |                const char *m_field);                       |
      |function::add a field in the current header with a data     |
      |          piece in metadata                                 |
      |input:                                                      |
      |     pgi                   packet graph instance            |
      |     p_field               field name in packet             |
      |     m_field               field name in metadata           |
      |output:                                                     |
      |     none                                                   |
      +------------------------------------------------------------+
      add_packet
      +------------------------------------------------------------+
 


<Author>               Expires December 21, 2018               [Page 11]

INTERNET DRAFT              <Document Title>               July 18, 2018


      |void add_packet(PGI *pgi,const char *p_field,value_t val);  |
      |function::add a field in the current header with a given    |
      |          value                                             |
      |input:                                                      |
      |     pgi                   packet graph instance            |
      |     p_field               field name in packet             |
      |     val                   given value                      |
      |output:                                                     |
      |     none                                                   |
      +------------------------------------------------------------+
      del_header
      +------------------------------------------------------------+
      |void del_header(PGI *pgi);                                  |
      |function::delete the current header, and the new current he-|
      |          ader becomes the outer header of the deleted one  |
      |input:                                                      |
      |     pgi                   packet graph instance            |
      |output:                                                     |
      |     none                                                   |
      +------------------------------------------------------------+
      del_field
      +------------------------------------------------------------+
      |bool del_field(PGI *pgi,const char *p_field);               |
      |function::delete a field from the current header            |
      |input:                                                      |
      |     pgi                   packet graph instance            |
      |     p_field               field name in packet             |
      |output:                                                     |
      |     if delete success,return true;else return false        |
      +------------------------------------------------------------+

4.2 Net Topology Search API

      PNPL uses a figure to show network topology,entity is the node of
      figure and every entity is on behalf of a switch or a host which
      is stored by adjacent list.Users use centralized algorithms in the
      figure to plan possible paths between any two hosts.

      Data structure of entity as follows:
      +------------------------------------------------------------+
      |enum entity_type { ENTITY_TYPE_HOST, ENTITY_TYPE_SWITCH };  |
      |struct entity_adj                                           |
      |{                                                           |
      |int out_port;                                               |
      |int adj_in_port;                                            |
      |struct entity *adj_entity;                                  |
      |};                                                          |
      +------------------------------------------------------------+
 


<Author>               Expires December 21, 2018               [Page 12]

INTERNET DRAFT              <Document Title>               July 18, 2018


      get_entity
      +------------------------------------------------------------+
      |struct entity **get_entity(struct entity *e,int port);      |
      |function::get entity which connects current entity          |
      |input:                                                      |
      |     e                     entity                           |
      |     port                  port number                      |
      |output:                                                     |
      |     entity                                                 |
      +------------------------------------------------------------+
      get_entity_type
      +------------------------------------------------------------+
      |enum entity_type get_entity_type(struct entity *e);         |
      |function::get the type of entity                            |
      |input:                                                      |
      |     e                     entity                           |
      |output                                                      |
      |     type of entity                                         |
      +------------------------------------------------------------+
      get_switch_dpid
      +------------------------------------------------------------+
      |dpid_t get_switch_dpid(struct entity *e);                   |
      |function::get dpid of entity switch                         |
      |input:                                                      |
      |     e                     entity                           |
      |output:                                                     |
      |     dpid                                                   |
      +------------------------------------------------------------+
      get_host_adj_switch
      +------------------------------------------------------------+
      |struct entity *get_host_adj_switch(struct entity *e,        |
      |                                   int *sw_port);           |
      |function::get host connecting switch                        |
      |input:                                                      |
      |     e                     entity                           |
      |output:                                                     |
      |     if e is a host,return its connecting switch            |
      |     sw_port is output ,return port number of switch        |
      +------------------------------------------------------------+
      get_entity_adjs
      +------------------------------------------------------------+
      |const struct entity_adj *get_entity_adjs(struct entity *e,  |
      |                                         int *pnum);        |
      |function::get adjacent list of entity                       |
      |input:                                                      |
      |     e                     entity                           |
      |output:                                                     |
      |     adjacent of entity                                     |
 


<Author>               Expires December 21, 2018               [Page 13]

INTERNET DRAFT              <Document Title>               July 18, 2018


      |     output parameter is pnum,return length of list         |
      +------------------------------------------------------------+
      print_entity
      +------------------------------------------------------------+
      |void print_entity(struct entity *e);                        |
      |function::output related information of entity              |
      |input:                                                      |
      |     e                     entity                           |
      |output:                                                     |
      +------------------------------------------------------------+
      get_switches
      +------------------------------------------------------------+
      |struct entity **getswitches(int *pnum);                     |
      |function::get all lists of switches in net                  |
      |input:                                                      |
      |     none                                                   |
      |output:                                                     |
      |     return all switch lists                                |
      |     output parameter is pnum,return number of switches     |
      +------------------------------------------------------------+
      get_switch
      +------------------------------------------------------------+
      |struct entity *get_switch(dpid_t dpid);                     |
      |function::search the switch according to dpid               |
      |input:                                                      |
      |     dpid                   switch number                   |
      |output:                                                     |
      |     switch entity whose switch number is dpid              |
      +------------------------------------------------------------+
      get_host_by_haddr
      +------------------------------------------------------------+
      |struct entity *get_host_by_haddr(haddr_t addr);             |
      |function::search host according to hardware address         |
      |input:                                                      |
      |     addr                   host hardware address           |
      |output:                                                     |
      |     host entity whose hardware address is addr             |
      +------------------------------------------------------------+
      get_host_by_paddr
      +------------------------------------------------------------+
      |struct entity *get_host_by_paddr(uint32_t addr);            |
      |function::search host according to protocol address         |
      |input:                                                      |
      |     addr                   host protocol address           |
      |output:                                                     |
      |     host entity whose protocol address is addr             |
      +------------------------------------------------------------+

 


<Author>               Expires December 21, 2018               [Page 14]

INTERNET DRAFT              <Document Title>               July 18, 2018


4.3 Path Planning API

      Network algorithm plans forwarding paths according to content of
      packet and topology.Type of route is struct route,which consists
      of some edges connecting source host and destination host.As
      follows:  
      +------------------------------------------------------------+
      |edge_t edge(struct entity *ent1,                            |
      |       int port1,                                           |
      |       struct entity *ent2,                                 |
      |       int port2);                                          |
      +------------------------------------------------------------+
      edge is a quad(ent1,port1,ent2,port2),shows an edge that comes out
      from ent1's port1 and comes into ent2's port2.

      PNPL supports Path Planning API:

      route
      +------------------------------------------------------------+
      |struct route *route(void);                                  |
      |function::create a new empty route                          |
      |input:                                                      |
      |     none                                                   |
      |output:                                                     |
      |     new route                                              |
      +------------------------------------------------------------+
      route_free
      +------------------------------------------------------------+
      |void route_free(struct route *r);                           |
      |function::free route                                        |
      |input:                                                      |
      |     r                     route waiting for free           |
      |output:                                                     |
      |     none                                                   |
      +------------------------------------------------------------+
      route_add_edge
      +------------------------------------------------------------+
      |void route_add_edge(struct route *r,edge_t e);              |
      |function::add edge into route                               |
      |input:                                                      |
      |     r                     route                            |
      |     e                     edge                             |
      |output:                                                     |
      +------------------------------------------------------------+
      route_union
      +------------------------------------------------------------+
      |void route_union(struct route *r1,struct route *r2);        |
      |function::merge route r1 and r2 into r1                     |
 


<Author>               Expires December 21, 2018               [Page 15]

INTERNET DRAFT              <Document Title>               July 18, 2018


      |input:                                                      |
      |     r1                     route r1                        |
      |     r2                     route r2                        |
      |output:                                                     |
      |     none                                                   |
      +------------------------------------------------------------+

5  Tracing Runtime System

5.1  Parse Graph and Parse Graph Instance

      After loading a header specification, PNPL derives a parse graph
      (PG) from it. A PG is a directed acyclic graph G = (V,E), where
      each node v represents a declared header,and each directed edge e
      from one node to another indicates a "next-layer protocol"
      relation between the two corresponding headers. Moreover, To cope
      with the dynamic nature of network packets in the wild, PNPL
      creates a data object named parse graph instance (PGI),which is a
      sub-graph of the PG and presents the packet parsing result.

5.2  Trace

      A trace in PNPL contains execution details of three categories of
      APIs in section 4. Each time an network policy is invoked, PNPL
      records its execution details as a trace. In PNPL, a trace
      generated from an network policy depends on two factors: the API
      execution sequence and the PGI accessed by the APIs.

5.3  Extended Tracing Tree

      An extended trace tree (xTT) is a rooted tree where each node t
      has an attribute type_t, whose value is one of L (leaf), V
      (value), T (testify), N (next table), WM (write metadata), or E
      (empty), such that:

      1) If type_t = L, then t has an opt attribute, which ranges over
      possible operations that can be done on the packet, such as
      forwarding/dropping the packet, adding/removing a header or a
      field to the packet, or modifying a packet filed. This node
      represents the behavior of a program that returns opt without
      further processing the packet.

      2) If type_t = V, then t has a tuple_t attribute and a subtree_t
      attribute, where tuple_t can be either a packet or a metadata
      tuple, and subtree_t is an associative array such that
      subtreet_t[val]... is a trace tree for value val belongs to
      keys(subtree_t)". This node represents the behavior of a program
      that if a given PGI i has a value val for tuple_t, i.e.,
 


<Author>               Expires December 21, 2018               [Page 16]

INTERNET DRAFT              <Document Title>               July 18, 2018


      i.[tuple_t] = val, then it continues with subtree_t[val].

      3) If type_t = T, then t has a tuple_t attribute and a value_t
      attribute, where tuple_t can be either a packet or a metadata
      tuple, and two subtree attributes subtree+ and subtree-. This node
      reflects the behavior that tests the assertion i.[tuple_t] =
      valuet of a given PGI i, then branches to subtree+ if true, and
      subtree- otherwise.

      4) If type_t = N, then t has an offset_t attribute, a header_t
      attribute, a tuple_list_t attribute, and a subtree attribute
      subtree_t. This node represents the behavior that moves the p-
      offset cursor with offset_t, forwards the packet to the next-stage
      flow table corresponding to header_t, which is one of the headers
      in the header specification, and continues with subtree_t. In case
      that the table does not exist, it is created on demand, with all
      the matching fields of header_t, as well as the metadata tuples in
      tuple_list_t, as the table's matching fields.

      5) If type_t = WM, then t has a dst_t attribute for a metadata
      tuple, a src_t attribute, which can be either a packet tuple, or a
      data value. This node reflects the behavior that writes the value
      at tuple src_t in the packet to a data piece at dst_t in the
      metadata, or directly write value src_t to dst_t, and continues
      with subtree_t.

      6) If type_t = E, then t has no attribute. This node represents an
      unknown behavior.

5.4  Forwarding Pipeline

      In each POF switch along the forwarding path, PNPL produces and
      maintains a forwarding pipeline (FP) generated from the xTT. In
      general, an FP consists of multiple flow tables (FTs), each can be
      viewed as a collection of (priority, match, operation) rules,
      where priority is a numerical priority, match is a combination of
      one or more {tuple, value} pairs, and operation is a concatenation
      of one or more instructions executed by POF switch on a matched
      packet (with its metadata).

5.5  Optimization

      The optimized method is like P4 which introduces eliminating
      unnecessary barrier rules and the "switch-level" parallelism on
      many-core platform. In PNPL, a same policy decision may be traced
      by multiple paths on the xTT, with only the difference on how the
      packets should be parsed. When there maybe exist redundancy rules
      to a same FT, we introduce a boolean attribute rdt, by default rdt
 


<Author>               Expires December 21, 2018               [Page 17]

INTERNET DRAFT              <Document Title>               July 18, 2018


      = false. Each time the xTT is augmented, we compare each pair of
      the PTs, say PT1 and PT2, that correspond to a same header, and
      decide whether they produce redundant rules. If all the paths to
      the L and N nodes within PT2 can be found in PT1, we say that PT2
      is redundant with PT1. When generating FP, if a rule-emitting node
      t belongs to a redundant PT, it is skipped without emitting any
      rule.

6  Example

      The following is the example for Ethernet IPv4 unicast. User need
      to define the protocol as follow:
      +------------------------------------+
      | header IPv4;                       |
      | header VLAN;                       |
      | header TCP;                        |
      | header UDP;                        |
      |                                    |
      | header Ethernet                    |
      |     fields                         |
      |         _mac_dst : 48;             |
      |         mac_src : 48;              |
      |         _ethertype : 16;           |
      |     next select (ethertype)        |
      |         case 0x0800 : IPv4;        |
      |         case 0x9100 : VLAN;        |
      | header VLAN                        |
      |     fields                         |
      |         prio : 3;                  |
      |         cfi : 1;                   |
      |         _vid : 12;                 |
      |         _ethertype : 16;           |
      |     next select (ethertype)        |
      |         case 0x0800 : IPv4;        |
      | header IPv4                        |
      |     fields                         |
      |         _ver_ihl : 8;              |
      |         tos : 8;                   |
      |         len : 16;                  |
      |         id : 16;                   |
      |         flag : 3;                  |
      |         off :13;                   |
      |         ttl : 8;                   |
      |         _proto : 8;                |
      |         sum :16;                   |
      |         _ip_src : 32;              |
      |         _ip_dst : 32;              |
      |         option : *;                |
 


<Author>               Expires December 21, 2018               [Page 18]

INTERNET DRAFT              <Document Title>               July 18, 2018


      |     length: (ver_ihl & 0x0F) <> 2; |
      |     next select (proto)            |
      |         case 0x06 : TCP;           |
      |         case 0x11 : UDP;           |
      +------------------------------------+


      After specifying the protocol,user can write the network algorithm
      in C language with PNPL API as follow.
      +------------------------------------------------+
      | Path * f(Packet *pkt, struct map *env){        |
      |     pgi = apply_PG(pkt);                       |
      |     if(search_header(pgi, "IPv4", {})){        |
      |         ipSrc = read_packet(pgi, "ip_src");    |
      |         ipDst = read_packet(pgi, "ip_dst");    |
      |         if(Lookup(LegitimateIPs, ipSrc)) {     |
      |             if(Lookup(LegitimateIPs, ipDst)){  |
      |                 return CalcPath(ipSrc, ipDst); |
      |             }                                  |
      |         }                                      |
      |     }                                          |
      |     return EmptyPath();                        |
      | }                                              |
      +------------------------------------------------+
      The algorithm first calls apply_PG to parse the unparsed PacketIn
      packet pkt with the PG and obtains a PGI; then the algorithm get
      the source and destination IP address in the pgi. examines whether
      the source IP is legitimate: If yes, the program calls the user-
      defined function calc_path to compute a network path from the
      source IP to the destination IP. Otherwise, an empty path is
      returned, that is, the packet will be dropped. If an non-empty
      path is returned, PNPL generates pipelines that implement the
      network policy described in the f function, and install them on
      each switch along the path.

7 Security Considerations

      The mechanism described in this document does not raise any new
      security issues for the PCEP protocols.

8 IANA Considerations

      This document includes no request to IANA.

9 Conclusion

      PNPL applies an efficient and easy-to-use control plane
      programming framework over POF networks. It supports a P4-like
 


<Author>               Expires December 21, 2018               [Page 19]

INTERNET DRAFT              <Document Title>               July 18, 2018


      header specification language, and provides high-level protocol-
      agnostic abstractions for composing algorithmic policies over POF
      networks. With the language, PNPL enables a programmer to
      arbitrarily define network protocols with complicated header
      structures, and with the APIs, a programmer can compose his
      network policy over the self-defined protocols, without worrying
      the data plane details. PNPL's tracing runtime system handles
      unparsed packets reported from the data plane, and automatically
      generates forwarding pipelines that simultaneously parse packets
      and enforce programmer's network policy. PNPL can effectively
      enable network innovations by simplifying POF programming,
      producing and maintaining forwarding pipelines of high quality.


10  References

10.1  Normative References

   [RFC7149]  Boucadair, M., "Software-Defined Networking: A Perspective
              from within a Service Provider Environment", RFC 7149,
              March 2014.

   [RFC7426]  E. Haleplidis, Ed., "Software-Defined Networking (SDN):
              Layers and Architecture Terminology", RFC 7426, January
              2015.


10.2  Informative References

   [OF-SPEC]  Open Networking Foundation, "OpenFlow Switch          
              Specification, version 1.5.1", October 2015,          
              <https://www.opennetworking.org>.


Authors' Addresses


              Ye Tian
              University of Science and Technology of China, 
              96 Jinzhai Rd., Hefei, Anhui, 230026, China.

              EMail: yetian@ustc.edu.cn









<Author>               Expires December 21, 2018               [Page 20]