<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      [dev][dpdk][crypto] dpdk加解密設備與IPSEC

      概述

      分三部分,加解密框架(crypto framework),加解密設備(crypto dev),安全協議(Security Framework)

      ×  API,設計思路等,都在加解密框架里:見文檔:http://doc.dpdk.org/guides-18.11/prog_guide/cryptodev_lib.html

      ×  設備層的事情,加解密設備的分類,調度,主備等,見文檔:http://doc.dpdk.org/guides-18.11/cryptodevs/index.html

      ×  ESP,PDCP等網絡加密協議相關的事情,主要功能是整合NIC pmd和Crypto pmd,見文檔:http://doc.dpdk.org/guides-18.11/prog_guide/rte_security.html

       

      另外還有一個追加的部分,ipsec (rte_ipsec)

      *  這一部分主要是對前面三個部分的整合封裝調用,用來專門處理ipsec報文。見文檔:http://doc.dpdk.org/guides/prog_guide/ipsec_lib.html

       

      畫個圖:

       

       

      如果,以上三個文檔,你都讀完了,那么請不要再往下讀了。內容重復。且本人懶惰,多以摘要為主,寫的也不好  :)

       

      一般編程模型

      畫了一張圖,還沒完全整理好,后續有可能會再更新,也有可能不更新了。

      是參考dpdk的這個例子里的流程畫的:http://doc.dpdk.org/guides/sample_app_ug/ipsec_secgw.html

       

      初始化加密設備的一般流程。

       

       

      設備就緒后的一般使用流程。(需要關注的是:在分析rte_ipsec的源碼過程中,并沒有發現對API rte_crypto_op_attach_sym_session的調用。奇怪。。。)

          // TODO init dpdk crypto things.
          // 1. init sa->xforms  like function sa_add_rules()
          // 2. init two parameter ipsec_xform/crypto_xform
          // 2. ipsec_sa_init()
          //    2.1 rte_ipsec_sa_init()
          // 3. create_session
          //    3.1 rte_security_session_create()
          //    3.2 rte_cryptodev_sym_session_create()
          //    3.3 rte_cryptodev_sym_session_init()
          // 3.4 rte_ipsec_session_prepare()
          //    3.4.1 sa->ips->pkt_func = ipsec_sa_pkt_func_select()
          // 3.5 rte_ipsec_pkt_process()
          //    3.5.1 sa->ips->pkt_func.process()
          // 3.6 rte_ipsec_pkt_crypto_prepare()
          //    3.6.1 sa->ips->pkt_func.prepare()
          // 7 rte_cryptodev_enqueue_burst()
          // 8.rte_cryptodev_dequeue_burst()
          // 9 rte_ipsec_pkt_crypto_group()
          // 10 rte_ipsec_pkt_process()
          //    3.5.1 sa->ips->pkt_func.process()
          // outbound
          // 4 rte_security_attach_session()
          // 5 rte_crypto_op_attach_sym_session()
          // 6 rte_security_set_pkt_metadata()
          // 7.rte_cryptodev_enqueue_burst()
          // 8 rte_cryptodev_dequeue_burst()

       

       

       

      第二部分,設備(crypto dev)

      所有的加解密設備大概分為以下幾種:openssl,null,硬件架構相關的設備。

      null為純軟件的最小實現,可以用來調試等。

      硬件相關的主要包括,Intel,arm,NXP,AMD,QAT卡等。

      還有一種,基于VIRTIO的PMD設備。

      不同的設備,所支持的加解密算法也各有不同,有一個詳細的對比列表,見:

      http://doc.dpdk.org/guides-18.11/cryptodevs/overview.html

      設備調度

      在各設備的上層,還有一個調度設備,用于管理和協調多個加解密設備直接的數據流。叫做 cryptodev scheduler PMD

      http://doc.dpdk.org/guides-18.11/cryptodevs/scheduler.html

       

      接口API

      加解密設備的調度API(schduler)

      http://doc.dpdk.org/api-18.11/rte__cryptodev__scheduler_8h.html

       

      加解密設備的使用API (cryptodev)

      http://doc.dpdk.org/api-18.11/rte__cryptodev_8h.html

       

      第一部分  框架(crypto framework)

      架構設計文檔:http://doc.dpdk.org/guides-18.11/prog_guide/cryptodev_lib.html

      設計理念

      The cryptodev library follows the same basic principles as those used in DPDKs Ethernet Device framework. 
      The Crypto framework provides a generic Crypto device framework which supports both physical (hardware)
      and virtual (software) Crypto devices as well as a generic Crypto API which allows Crypto devices to be
      managed and configured and supports Crypto operations to be provisioned on Crypto poll mode driver.

      設備初始化方法

      A。 初始化設備

      實體設備:與PCI網卡相同。

      虛擬設備:1. 可以使用 --vdev參數在dpdk程序啟動時使用。2. 在運行時使用api:

      rte_vdev_init("crypto_aesni_mb",
                        "max_nb_queue_pairs=2,socket_id=0")

       

      B。配置設備

      設備識別:用Id或name

      設備配置:使用api:

      int rte_cryptodev_configure(uint8_t dev_id,
                                  struct rte_cryptodev_config *config)
      
      struct rte_cryptodev_config {
          int socket_id;
          /**< Socket to allocate resources on */
          uint16_t nb_queue_pairs;
          /**< Number of queue pairs to configure on device */
      };

       

      C。配置queue

      int rte_cryptodev_queue_pair_setup(uint8_t dev_id, uint16_t queue_pair_id,
                  const struct rte_cryptodev_qp_conf *qp_conf,
                  int socket_id)
      
      struct rte_cryptodev_qp_conf {
          uint32_t nb_descriptors; /**< Number of descriptors per queue pair */
      };

       

      D。數據流程

      1.  在queue pair 上burst 提取數據。

      uint16_t rte_cryptodev_enqueue_burst(uint8_t dev_id, uint16_t qp_id,
                                           struct rte_crypto_op **ops, uint16_t nb_ops)
      uint16_t rte_cryptodev_dequeue_burst(uint8_t dev_id, uint16_t qp_id,
                                           struct rte_crypto_op **ops, uint16_t nb_ops)

       

      2.  私有數據的存儲。分基于session的和不基于session的兩種情況。

      3. 關鍵的用于加解密操作的數據結構 rte_crypto_op, 可以把op理解為mbuf,op是mempool管理的。

      4. op的mempool的API

      extern struct rte_mempool *
      rte_crypto_op_pool_create(const char *name, enum rte_crypto_op_type type,
                                unsigned nb_elts, unsigned cache_size, uint16_t priv_size,
                                int socket_id);
      struct rte_crypto_op *rte_crypto_op_alloc(struct rte_mempool *mempool,
                                                enum rte_crypto_op_type type)
      
      unsigned rte_crypto_op_bulk_alloc(struct rte_mempool *mempool,
                                        enum rte_crypto_op_type type,
                                        struct rte_crypto_op **ops, uint16_t nb_ops)
      void rte_crypto_op_free(struct rte_crypto_op *op)

       

      5. session

      session用來存儲加密過程中的key,以及分組信息等。

      用來存儲這些的叫做private session data

      api:

      rte_cryptodev_sym_session_create()
      rte_cryptodev_sym_session_init()
      rte_cryptodev_sym_session_clear()
      rte_cryptodev_sym_session_free()

       

      6. transforms

      Currently there are three transforms types cipher, authentication and AEAD. 
      Also it is important to note that the order in which the transforms are passed indicates the order of the chaining.
      struct rte_crypto_sym_xform {
          struct rte_crypto_sym_xform *next;
          /**< next xform in chain */
          enum rte_crypto_sym_xform_type type;
          /**< xform type */
          union {
              struct rte_crypto_auth_xform auth;
              /**< Authentication / hash xform */
              struct rte_crypto_cipher_xform cipher;
              /**< Cipher xform */
              struct rte_crypto_aead_xform aead;
              /**< AEAD xform */
          };
      };

       

      7. 運行狀態下的最小配置

      As a minimum the symmetric operation must have a source data buffer (m_src), a valid session (or transform chain if in session-less mode) and the minimum authentication/ cipher/ AEAD parameters 
      required depending on the type of operation specified in the session or the transform chain.

      示例程序:

      /*
       * Simple example to encrypt several buffers with AES-CBC using
       * the Cryptodev APIs.
       */
      
      #define MAX_SESSIONS         1024
      #define NUM_MBUFS            1024
      #define POOL_CACHE_SIZE      128
      #define BURST_SIZE           32
      #define BUFFER_SIZE          1024
      #define AES_CBC_IV_LENGTH    16
      #define AES_CBC_KEY_LENGTH   16
      #define IV_OFFSET            (sizeof(struct rte_crypto_op) + \
                                   sizeof(struct rte_crypto_sym_op))
      
      struct rte_mempool *mbuf_pool, *crypto_op_pool, *session_pool;
      unsigned int session_size;
      int ret;
      
      /* Initialize EAL. */
      ret = rte_eal_init(argc, argv);
      if (ret < 0)
          rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n");
      
      uint8_t socket_id = rte_socket_id();
      
      /* Create the mbuf pool. */
      mbuf_pool = rte_pktmbuf_pool_create("mbuf_pool",
                                      NUM_MBUFS,
                                      POOL_CACHE_SIZE,
                                      0,
                                      RTE_MBUF_DEFAULT_BUF_SIZE,
                                      socket_id);
      if (mbuf_pool == NULL)
          rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n");
      
      /*
       * The IV is always placed after the crypto operation,
       * so some private data is required to be reserved.
       */
      unsigned int crypto_op_private_data = AES_CBC_IV_LENGTH;
      
      /* Create crypto operation pool. */
      crypto_op_pool = rte_crypto_op_pool_create("crypto_op_pool",
                                              RTE_CRYPTO_OP_TYPE_SYMMETRIC,
                                              NUM_MBUFS,
                                              POOL_CACHE_SIZE,
                                              crypto_op_private_data,
                                              socket_id);
      if (crypto_op_pool == NULL)
          rte_exit(EXIT_FAILURE, "Cannot create crypto op pool\n");
      
      /* Create the virtual crypto device. */
      char args[128];
      const char *crypto_name = "crypto_aesni_mb0";
      snprintf(args, sizeof(args), "socket_id=%d", socket_id);
      ret = rte_vdev_init(crypto_name, args);
      if (ret != 0)
          rte_exit(EXIT_FAILURE, "Cannot create virtual device");
      
      uint8_t cdev_id = rte_cryptodev_get_dev_id(crypto_name);
      
      /* Get private session data size. */
      session_size = rte_cryptodev_sym_get_private_session_size(cdev_id);
      
      /*
       * Create session mempool, with two objects per session,
       * one for the session header and another one for the
       * private session data for the crypto device.
       */
      session_pool = rte_mempool_create("session_pool",
                                      MAX_SESSIONS * 2,
                                      session_size,
                                      POOL_CACHE_SIZE,
                                      0, NULL, NULL, NULL,
                                      NULL, socket_id,
                                      0);
      
      /* Configure the crypto device. */
      struct rte_cryptodev_config conf = {
          .nb_queue_pairs = 1,
          .socket_id = socket_id
      };
      struct rte_cryptodev_qp_conf qp_conf = {
          .nb_descriptors = 2048
      };
      
      if (rte_cryptodev_configure(cdev_id, &conf) < 0)
          rte_exit(EXIT_FAILURE, "Failed to configure cryptodev %u", cdev_id);
      
      if (rte_cryptodev_queue_pair_setup(cdev_id, 0, &qp_conf,
                              socket_id, session_pool) < 0)
          rte_exit(EXIT_FAILURE, "Failed to setup queue pair\n");
      
      if (rte_cryptodev_start(cdev_id) < 0)
          rte_exit(EXIT_FAILURE, "Failed to start device\n");
      
      /* Create the crypto transform. */
      uint8_t cipher_key[16] = {0};
      struct rte_crypto_sym_xform cipher_xform = {
          .next = NULL,
          .type = RTE_CRYPTO_SYM_XFORM_CIPHER,
          .cipher = {
              .op = RTE_CRYPTO_CIPHER_OP_ENCRYPT,
              .algo = RTE_CRYPTO_CIPHER_AES_CBC,
              .key = {
                  .data = cipher_key,
                  .length = AES_CBC_KEY_LENGTH
              },
              .iv = {
                  .offset = IV_OFFSET,
                  .length = AES_CBC_IV_LENGTH
              }
          }
      };
      
      /* Create crypto session and initialize it for the crypto device. */
      struct rte_cryptodev_sym_session *session;
      session = rte_cryptodev_sym_session_create(session_pool);
      if (session == NULL)
          rte_exit(EXIT_FAILURE, "Session could not be created\n");
      
      if (rte_cryptodev_sym_session_init(cdev_id, session,
                      &cipher_xform, session_pool) < 0)
          rte_exit(EXIT_FAILURE, "Session could not be initialized "
                      "for the crypto device\n");
      
      /* Get a burst of crypto operations. */
      struct rte_crypto_op *crypto_ops[BURST_SIZE];
      if (rte_crypto_op_bulk_alloc(crypto_op_pool,
                              RTE_CRYPTO_OP_TYPE_SYMMETRIC,
                              crypto_ops, BURST_SIZE) == 0)
          rte_exit(EXIT_FAILURE, "Not enough crypto operations available\n");
      
      /* Get a burst of mbufs. */
      struct rte_mbuf *mbufs[BURST_SIZE];
      if (rte_pktmbuf_alloc_bulk(mbuf_pool, mbufs, BURST_SIZE) < 0)
          rte_exit(EXIT_FAILURE, "Not enough mbufs available");
      
      /* Initialize the mbufs and append them to the crypto operations. */
      unsigned int i;
      for (i = 0; i < BURST_SIZE; i++) {
          if (rte_pktmbuf_append(mbufs[i], BUFFER_SIZE) == NULL)
              rte_exit(EXIT_FAILURE, "Not enough room in the mbuf\n");
          crypto_ops[i]->sym->m_src = mbufs[i];
      }
      
      /* Set up the crypto operations. */
      for (i = 0; i < BURST_SIZE; i++) {
          struct rte_crypto_op *op = crypto_ops[i];
          /* Modify bytes of the IV at the end of the crypto operation */
          uint8_t *iv_ptr = rte_crypto_op_ctod_offset(op, uint8_t *,
                                                  IV_OFFSET);
      
          generate_random_bytes(iv_ptr, AES_CBC_IV_LENGTH);
      
          op->sym->cipher.data.offset = 0;
          op->sym->cipher.data.length = BUFFER_SIZE;
      
          /* Attach the crypto session to the operation */
          rte_crypto_op_attach_sym_session(op, session);
      }
      
      /* Enqueue the crypto operations in the crypto device. */
      uint16_t num_enqueued_ops = rte_cryptodev_enqueue_burst(cdev_id, 0,
                                              crypto_ops, BURST_SIZE);
      
      /*
       * Dequeue the crypto operations until all the operations
       * are proccessed in the crypto device.
       */
      uint16_t num_dequeued_ops, total_num_dequeued_ops = 0;
      do {
          struct rte_crypto_op *dequeued_ops[BURST_SIZE];
          num_dequeued_ops = rte_cryptodev_dequeue_burst(cdev_id, 0,
                                          dequeued_ops, BURST_SIZE);
          total_num_dequeued_ops += num_dequeued_ops;
      
          /* Check if operation was processed successfully */
          for (i = 0; i < num_dequeued_ops; i++) {
              if (dequeued_ops[i]->status != RTE_CRYPTO_OP_STATUS_SUCCESS)
                  rte_exit(EXIT_FAILURE,
                          "Some operations were not processed correctly");
          }
      
          rte_mempool_put_bulk(crypto_op_pool, (void **)dequeued_ops,
                                              num_dequeued_ops);
      } while (total_num_dequeued_ops < num_enqueued_ops);

       

      第三部分,Security Framework

      前邊的內容,都在講加解密。但是實際上呢,我是想要處理IPSEC的報文。下面這個庫,將搞定這個事情:

      http://doc.dpdk.org/guides-18.11/prog_guide/rte_security.html

       

      既然是ipsec,所以,自然用到nic和crypto兩部分的pmd

             +---------------+
             | rte_security  |
             +---------------+
               \            /
      +-----------+    +--------------+
      |  NIC PMD  |    |  CRYPTO PMD  |
      +-----------+    +--------------+

       

      硬件offload 

      加解密offload

      就是說收到的包就解好了密,發包之前不需要進行包加密的意思。這個是硬件offload支持的,不支持的話,還是需要軟件去把包送給crypto dev 處理。

      協議offload

      區別于加解密offload,ESP的包頭之類的,也可以offload的給硬件。

      lookaside offload

      處理前邊提到那兩個,就連sa的管理,也可以直接offload。

       

      設備能力

      ipsec的封解包,是由device決定的。不同的device可能不一定支持,需要通過下面的方法具體查看。這里的device即包括了eth也包括了crypto

      The device (crypto or ethernet) capabilities which support security operations, are defined by the security action type, security protocol, 
      protocol capabilities and corresponding crypto capabilities for security. For the full scope of the Security capability see definition of
      rte_security_capability structure in the DPDK API Reference.

      API:

      const struct rte_security_capability *rte_security_capabilities_get(uint16_t id);

       

      安全會話(security session)

      Security Sessions are created to store the immutable fields of a particular Security Association for a particular protocol which is defined by a security session 
      configuration structure which is used in the operation processing of a packet flow. Sessions are used to manage protocol specific information as well as crypto
      parameters. Security sessions cache this immutable data in a optimal way for the underlying PMD and this allows further acceleration of the offload of Crypto workloads.

      session也是mempool里的內存

      sessions are mempool objects.

       

      API:

      http://doc.dpdk.org/api/rte__security_8h.html

      rte_security_session_create()
      rte_cryptodev_get_sec_ctx() or  rte_eth_dev_get_sec_ctx()
      rte_security_session_destroy()

      關鍵結構體

      rte_security_session_conf

      struct rte_security_session_conf {
          enum rte_security_session_action_type action_type;
          /**< Type of action to be performed on the session */
          enum rte_security_session_protocol protocol;
          /**< Security protocol to be configured */
          union {
                  struct rte_security_ipsec_xform ipsec;
                  struct rte_security_macsec_xform macsec;
                  struct rte_security_pdcp_xform pdcp;
          };
          /**< Configuration parameters for security session */
          struct rte_crypto_sym_xform *crypto_xform;
          /**< Security Session Crypto Transformations */
          void *userdata;
          /**< Application specific userdata to be saved with session */
      };
      enum rte_security_session_action_type {
          RTE_SECURITY_ACTION_TYPE_NONE,
          /**< No security actions */
          RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
          /**< Crypto processing for security protocol is processed inline
           * during transmission */
          RTE_SECURITY_ACTION_TYPE_INLINE_PROTOCOL,
          /**< All security protocol processing is performed inline during
           * transmission */
          RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL
          /**< All security protocol processing including crypto is performed
           * on a lookaside accelerator */
      };

       

      其他

      如果是NIC設備的offload,必須注意flow和加解密序列和port直接的對應關系。

      In the case of NIC based offloads, the security session specified in the ‘rte_flow_action_security’ 
      must be created on the same port as the flow action that is being specified.

       

      第四部分 RTE_IPSEC

      文檔: http://doc.dpdk.org/guides/prog_guide/ipsec_lib.html

      一般使用流程

      /* enqueue for processing by crypto-device */
      rte_ipsec_pkt_crypto_prepare(...);
      rte_cryptodev_enqueue_burst(...);
      /* dequeue from crypto-device and do final processing (if any) */
      rte_cryptodev_dequeue_burst(...);
      rte_ipsec_pkt_crypto_group(...); /* optional */
      rte_ipsec_pkt_process(...);

       

      api:

      這個還沒發布。。。 在master分支上,模塊名字叫librte_ipsec

      詳細的用法可以見頭文件: http://git.dpdk.org/dpdk/tree/lib/librte_ipsec/rte_ipsec.h?h=releases

       

      posted on 2019-03-04 11:49  toong  閱讀(7924)  評論(0)    收藏  舉報

      主站蜘蛛池模板: 99久久精品久久久久久婷婷| 极品无码国模国产在线观看| 国产午夜精品福利免费看| 中文国产人精品久久蜜桃| 婷婷开心色四房播播| 最新精品国偷自产在线美女足| 日韩理伦片一区二区三区| 国产中文三级全黄| 亚洲欧美日韩在线码| 亚洲色大成网站WWW久久| 草草浮力影院| 亚洲无人区视频在线观看| 贺兰县| 国产精品白丝久久av网站| аⅴ天堂中文在线网| 国产三级精品三级在线区| 性欧美vr高清极品| 亚洲男人的天堂一区二区| 国产成人午夜福利在线观看| 亚洲色最新高清AV网站| 熟妇人妻中文a∨无码| 国产亚洲精品黑人粗大精选| 国产在线精品中文字幕| 少妇人妻真实偷人精品| 四虎永久地址www成人| 国产午夜视频在线观看| 老色鬼在线精品视频在线观看| 国产精品麻豆成人AV电影艾秋 | 日本午夜精品一区二区三区电影| 东兰县| 亚洲第一无码AV无码专区| 亚洲乱熟乱熟女一区二区| 久久夜色精品国产亚av| 免费十八禁一区二区三区| 日本午夜精品一区二区三区电影| 九江市| 免费无遮挡毛片中文字幕| www国产亚洲精品久久网站| 大地资源中文第二页日本| 亚洲精品入口一区二区乱| 亚洲国产一区二区三区最新|