• <xmp id="om0om">
  • <table id="om0om"><noscript id="om0om"></noscript></table>
  • Networking

    NVIDIA BlueField DPU と NVIDIA DOCA ライブラリによるアプリケーション開発

    Reading Time: 3 minutes

    この投稿では、FRR DOCA データプレーン プラグインの作成方法と、新しい DOCA フロー ライブラリを使用して PBR ルールをオフロードする方法を紹介します。前回の記事では、DPDK rte_flow ライブラリを使用して BlueField 上の PBR ルールを高速化するための FRR データプレーン プラグインの作成について説明しましたが、今回は、DOCA フロー ライブラリを使用して PBR ルール をオフロードする方法について説明します。パート 1 については、NVIDIA BlueField DPU と DPDK を使ったアプリケーションの開発をご覧ください。

    Zebra に DOCA データプレーン プラグインを追加する

    ハードウェアの初期化には DPDK API を使いましたが、データプレーン フローのパイプラインのセットアップには DOCA フローのAPI を使いました。そのためには、DPDK (libdpdk.pc) と DOCA フロー (doca-flow.pc) の共有ライブラリを DOCA データプレーン プラグインとリンクする必要がありました。

    root@dpu-arm:~# export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/opt/mellanox/dpdk/lib/aarch?
    64-linux-gnu/pkgconfig?
    root@dpu-arm:~# pkg-config --libs doca-flow?
    -ldoca_flow?
    root@dpu-arm:~# pkg-config --cflags doca-flow?
    -DALLOW_EXPERIMENTAL_API -include rte_config.h -mcpu=cortex-a72 -DALLOW_EXPERIMENTAL_API -I/opt/mellanox/dpdk/include/dpdk -I/opt/mellanox/dpdk/include/dpdk/../aarch64-linux-gnu/dpdk -I/opt/mellanox/dpdk/include/dpdk -I/usr/include/libnl3?
    root@dpu-arm:~#?

    FRR の makefile (configure.ac) に DPDK と DOCA フローの pkg check and-define macro を追加しました。

    if test "$enable_dp_doca" = "yes"; then?
    ? PKG_CHECK_MODULES([DOCA], [libdpdk doca-flow], [?
    ??? AC_DEFINE([HAVE_DOCA], [1], [Enable DOCA backend])?
    ??? DOCA=true?
    ? ], [?
    ??? AC_MSG_ERROR([configuration specifies --enable-dp-doca but DOCA libs were not found])?
    ? ])?
    fi

    DPDK と DOCA 両方の flow libs と cflagszebra-dp-doca make のマクロ (zebra/subdir.am) に入れました。

    zebra_zebra_dplane_doca_la_CFLAGS = $(DOCA_CFLAGS)?
    zebra_zebra_dplane_doca_la_LIBADD? = $(DOCA_LIBS)?

    DOCA データプレーン プラグインは、/etc/frr/daemons を使用して FRR サービス開始時に有効化することができます。

    zebra_options= " -M dplane_doca -A 127.0.0.1"

    ハードウェアの初期化およびポート マッピング

    DPDK API のrte_eal_initrte_eth_dev_info_get を使用して、ハードウェアの初期化と Zebra インターフェイスと DPDK ポート マッピングのセットアップを行います。このワークフローは、前述の DPDK データプレーン プラグインと同じです。

    root@dpu-arm:~# vtysh -c "show dplane doca port"?
    Total ports: 6 cores: 8?
    Port Device?????????? IfName?????????? IfIndex????????? sw,domain,port?
    0??? 0000:03:00.0???? p0?????????????? 4??????????????? 0000:03:00.0,0,65535?
    1??? 0000:03:00.0???? pf0hpf?????????? 6??????????????? 0000:03:00.0,0,4095?
    2??? 0000:03:00.0???? pf0vf0?????????? 15?????????????? 0000:03:00.0,0,4096?
    3??? 0000:03:00.0???? pf0vf1?????????? 16?????????????? 0000:03:00.0,0,4097?
    4??? 0000:03:00.1???? p1?????????????? 5??????????????? 0000:03:00.1,1,65535?
    5??? 0000:03:00.1???? pf1hpf?????????? 7??????????????? 0000:03:00.1,1,20479?
    root@dpu-arm:~#

    DOCA フロー初期化

    PBR ルールのプログラミングに doca-flow を使うには、doca-flowdoca-flow-port のデータベースを初期化する必要がありました。この初期化は、rte_eal_init を使ってハードウェアを初期化した後に行われました。

    doca_flow_init は、フローとキュー數の設定をして、doca-flow ライブラリを初期化するために使用しました。

    struct doca_flow_cfg flow_cfg;?
    
    memset(&flow_cfg, 0, sizeof(flow_cfg));?
    flow_cfg.total_sessions = ZD_DOCA_FLOW_MAX;?
    flow_cfg.queues = doca_ctx->nb_cores;
    ?
    doca_flow_init(&flow_cfg, &err);?

    DPDK を使ってハードウェア ポートを設定したので、doca-flow-port データベースに dpdk_port-id でインストールする必要がありました。

    struct doca_flow_port_cfg port_cfg;?

    ?memset(&port_cfg, 0, sizeof(port_cfg));?
    port_cfg.port_id = dpdk_port_id;?
    port_cfg.type = DOCA_FLOW_PORT_DPDK_BY_ID;?
    snprintf(port_id_str, ZD_PORT_STR_MAX, "%u", port_cfg.port_id);?
    port_cfg.devargs = port_id_str;?

    doca_port = doca_flow_port_start(&port_cfg, &err);

    doca-flow の API を使った PBR ルールのプログラム

    DOCA フローは、match、action、forward、monitor の各屬性に対応した一連のデータ構造でプログラムされています。

    struct doca_flow_match match, match_mask;?
    struct doca_flow_actions actions;?
    struct doca_flow_fwd fwd;?
    struct doca_flow_monitor monitor;

    フロー マッチ

    これは、match と match-mask で指定されます。match-mask はオプションであり、指定しない場合は doca-flow ライブラリによって自動入力されます。

    memset(&match, 0, sizeof(match));?
    memset(&match_mask, 0, sizeof(match_mask)); ?

    match.out_src_ip.type = DOCA_FLOW_IP4_ADDR;?
    match.out_src_ip.ipv4_addr = src_ip;?
    match_mask.out_src_ip.ipv4_addr = src_ip_mask;?

    match.out_dst_ip.type = DOCA_FLOW_IP4_ADDR;?
    match.out_dst_ip.ipv4_addr = dst_ip;?
    match_mask.out_src_ip.ipv4_addr = dst_ip_mask;?
    ?
    match.out_l4_type = ip_proto; ?
    ?
    match.out_src_port = RTE_BE16 (l4_src_port);?
    match_mask.out_src_port =? UINT16_MAX;?

    match.out_dst_port =? RTE_BE16 (l4_dst_port);?
    match_mask.out_dst_port =? UINT16_MAX;?

    etheth-mask などのフィールドは追加しないようにしました。これは、doca-flow ライブラリが、他のマッチ フィールドである dst_ipsrc_ip に基づいて、RTE_ETHER_TYPE_IPV4RTE_ETHER_TYPE_IPV6 にそのフィールドを自動追加することができるからです。

    フロー アクション

    パケットをルーティングするために、宛先 MAC アドレスをゲートウェイ (leaf2) の MAC に変更し、TTL を減少し、送信元 MAC アドレスを変更する必要がありました。これは元々、パート 1「Developing Applications with NVIDIA BlueField DPU and DPDK」で説明したものです。

    memset(&actions, 0, sizeof(actions));?
    
    ?actions.dec_ttl = true;?
    ?memcpy(actions.mod_src_mac, uplink_mac, DOCA_ETHER_ADDR_LEN);?
     memcpy(actions.mod_dst_mac, gw_mac, DOCA_ETHER_ADDR_LEN);?

    フロー フォワード

    そして、出力ポートをアップリンクに設定しました。

    memset(&fwd, 0, sizeof(fwd));?
    ?
    fwd.type = DOCA_FLOW_FWD_PORT;?
    fwd.port_id = out_port_id;?

    フロー モニタリング

    トラブルシューティングのためにフロー カウンターを設定しました。

    memset(&monitor, 0, sizeof(monitor));??
    monitor.flags |= DOCA_FLOW_MONITOR_COUNT;?

    DOCA フロー パイプとエントリ

    フローの作成は、2 つのステップで行います。

    1. フロー パイプを作成します。
    2. フロー パイプにフロー エントリを追加します。

    最初のステップでは、Lookup ステージのソフトウェア テンプレートが作成されます。ステップ 2 では、このテンプレートを使って、ハードウェアにフローをプログラムします。

    パイプは、多くの類似したフローをプログラムする必要がある場合に便利です。このような場合、1 つのマッチ テンプレート (パイプ) を設定し、フロー エントリ作成時にどのマッチ フィールドを更新する必要があるかを示すことができます (例: レイヤー 4 の宛先ポート)。後続のフロー エントリは、パイプ (レイヤー 4 の宛先ポート) と異なるマッチ フィールドにのみ追加する必要があります。

    PBR の場合、各フロー パターンがユニークなので、すでに追加していたフロー屬性を使って、PBR ルールごとに別のパイプとエントリを作成しました。

    struct doca_flow_pipe_cfg pipe_cfg;??

    pipe_cfg.name = "pbr";?
    pipe_cfg.port = in_dport->doca_port;?
    pipe_cfg.match = &match;?
    pipe_cfg.match_mask = &match_mask;?
    pipe_cfg.actions = &actions;?
    pipe_cfg.monitor = &monitor;?
    pipe_cfg.is_root = true;?

    flow_pipe = doca_flow_create_pipe(&pipe_cfg, &fwd, NULL, &err);?
    flow_entry = doca_flow_pipe_add_entry(0, flow_pipe, &match, &actions, &monitor, &fwd, &err);

    フローの削除

    フロー パイプとエントリ作成の API は、その後の削除のためにキャッシュされなければならないパイプとフロー ポインターを返します。

    doca_flow_pipe_rm_entry(0, flow_entry);?
    doca_flow_destroy_pipe(port_id, flow_pipe);?

    フローの統計

    フロー作成時に、DOCA_FLOW_MONITOR_COUNT フラグを設定しました。doca_flow_query を使用して、フローの統計情報を照會しました。

    struct doca_flow_query query;?

    // hit counters – query.total_pkts and query.total_bytes?
    memset(&query, 0, sizeof(query));?
    doca_flow_query(flow_entry,? &query);?

    ハードウェア アクセラレーションの検証

    FRR-PBR のルール設定とトラフィック生成は dpdk-plugin と同じです。トラフィックは DPU ハードウェアによって期待通りに転送され、フロー カウンターを使用して検証することが可能です。

    root@dpu-arm:~# vtysh -c "show dplane doca pbr flow"?
    Rules if pf0vf0?
    ? Seq 1 pri 300?
    ? SRC IP Match: 172.20.0.8/32?
    ? DST IP Match: 172.30.0.8/32?
    ? IP protocol Match: 17?
    ? DST Port Match: 53?
    ? Tableid: 10000?
    ? Action: nh: 192.168.20.250 intf: p0?
    ? Action: mac: 00:00:5e:00:01:fa?
    ? DOCA flow: installed 0xffff28005150?
    ? DOCA stats: packets 202 bytes 24644?
    root@dpu-arm:~#?

    また、ハードウェア エントリを用いて検証することも可能です。

    root@dpu-arm:~# ~/mlx_steering_dump/mlx_steering_dump_parser.py -p `pidof zebra`? -?
    f /tmp/dpdkDump?
    domain 0xe294002, table 0xaaab07648b10, matcher 0xffff28012c30, rule 0xffff28014040?
    ?? match: outer_l3_type: 0x1, outer_ip_dst_addr: 172.30.0.8, outer_l4_type: 0x2, metadata_reg_c_0: 0x00030000, outer_l4_dport: 0x0035, outer_ip_src_addr: 172.20.0.8?
    ?? action: MODIFY_HDR(hdr(dec_ip4_ttl)), rewrite index 0x0 & VPORT, num 0xffff & CTR(hits(352), bytes(42944)), index 0x806200

    FRR に、doca-flow を用いた PBR ルールのハードウェア アクセラレーションのための 2 つ目のデータプレーン プラグインが追加されました。

    アプリケーション開発のポイント

    この連載では、DPU ネットワーク アプリケーションを rte_flowdoca_flow を使用して 4 つのステップでハードウェア アクセラレーションする方法について見てきました。

    • DOCA/DPDK ライブラリをアプリケーションにリンクする。
    • ハードウェアを初期化する。
    • ハードウェアのポート マッピングのためにアプリケーションを設定する。
    • トラフィックを操るためのフローをプログラムする。

    DPU にオフロードされる要素が増えると、ソース コードの行數 (SLOC) が増え、開発プロセスが複雑になることがあります。そこで役立つのが DOCA アブストラクションです。

    • DOCA には、doca-dpi、gRPC、Firefly の時刻同期などの、いくつかの組み込みライブラリが用意されています。これらのライブラリにより、お客様のアプリケーションに素早くプラグアンドプレイで対応することができます。
    • doca_pipeなどの DOCA コンストラクトにより、パイプラインをテンプレート化し、定型的なコードを排除し、フローの挿入を最適化することができます。
    • 今後登場する DOCA ライブラリでは、ハードウェア アクセラレーションによる LPM (Longest prefix match) などにより、スイッチ パイプラインの構築が容易になります。特に、本連載で紹介したサンプル アプリケーションの FRR に関連しており、BGP で LPM ルーティング テーブル (または RIB) を構築するためによく展開されます。
    • DOCA を使えば、コンバージド アクセラレータ上での GPU+DPU 開発というエキサイティングな世界へも飛び込むことができるのです。
    図 1. コンバージド アクセラレータ

    あなたのアプリケーション開発をめくるめく高みへと導く準備はできましたか? DOCA 早期アクセス開発者プログラムに登録して、今すぐ開発を始めましょう。

    詳細は、以下の関連情報をご覧ください。

    翻訳に関する免責事項

    この記事は、「Developing Applications with NVIDIA BlueField DPU and NVIDIA DOCA Libraries」の抄訳で、お客様の利便性のために機械翻訳によって翻訳されたものです。NVIDIA では、翻訳の正確さを期すために注意払っておりますが、翻訳の正確性については保証いたしません。翻訳された記事の內容の正確性に関して疑問が生じた場合は、原典である英語の記事を參照してください。

    +2

    Tags

    人人超碰97caoporen国产