今日も秋田で IoT

旧 Trema 日記

Match 条件の wildcard について

Match 中の wildcard について説明します。

前回記事で作成した matchtest.rb を動かしてみましょう。

$ ./trema run ./matchtest.rb -c ./network.conf -d
$ TREMA_HOME=. ../apps/flow_dumper/flow_dumper
[0x00000000000001] priority = 65535, match = [wildcards = 0x3220ef, in_port = 0, dl_src = 00:00:00:00:00:00, dl_dst = 00:00:00:00:00:00, dl_vlan = 0, dl_vlan_pcp = 0, dl_type = 0x800, nw_tos = 0, nw_proto = 0, nw_src = 0.0.0.0/0, nw_dst = 192.168.1.0/24, tp_src = 0, tp_dst = 0], actions = []

flow_dumper の出力中に wildcards = 0x3220ef という表示があることが確認できます。二進数で表現すると、 11,0010,0010,0000,1110,1111b となります。この値は 12-tuple のうち、どのフィールドを wildcard として扱うかを示しています。各ビットとフィールドの対応は openflow.h 中にて以下のように定義されています。

/* Flow wildcards. */
enum ofp_flow_wildcards {
    OFPFW_IN_PORT  = 1 << 0,  /* Switch input port. */
    OFPFW_DL_VLAN  = 1 << 1,  /* VLAN id. */
    OFPFW_DL_SRC   = 1 << 2,  /* Ethernet source address. */
    OFPFW_DL_DST   = 1 << 3,  /* Ethernet destination address. */
    OFPFW_DL_TYPE  = 1 << 4,  /* Ethernet frame type. */
    OFPFW_NW_PROTO = 1 << 5,  /* IP protocol. */
    OFPFW_TP_SRC   = 1 << 6,  /* TCP/UDP source port. */
    OFPFW_TP_DST   = 1 << 7,  /* TCP/UDP destination port. */

    /* IP source address wildcard bit count.  0 is exact match, 1 ignores the
     * LSB, 2 ignores the 2 least-significant bits, ..., 32 and higher wildcard
     * the entire field.  This is the *opposite* of the usual convention where
     * e.g. /24 indicates that 8 bits (not 24 bits) are wildcarded. */
    OFPFW_NW_SRC_SHIFT = 8,
    OFPFW_NW_SRC_BITS = 6,
    OFPFW_NW_SRC_MASK = ((1 << OFPFW_NW_SRC_BITS) - 1) << OFPFW_NW_SRC_SHIFT,
    OFPFW_NW_SRC_ALL = 32 << OFPFW_NW_SRC_SHIFT,

    /* IP destination address wildcard bit count.  Same format as source. */
    OFPFW_NW_DST_SHIFT = 14,
    OFPFW_NW_DST_BITS = 6,
    OFPFW_NW_DST_MASK = ((1 << OFPFW_NW_DST_BITS) - 1) << OFPFW_NW_DST_SHIFT,
    OFPFW_NW_DST_ALL = 32 << OFPFW_NW_DST_SHIFT,

    OFPFW_DL_VLAN_PCP = 1 << 20,  /* VLAN priority. */
    OFPFW_NW_TOS = 1 << 21,  /* IP ToS (DSCP field, 6 bits). */

    /* Wildcard all fields. */
    OFPFW_ALL = ((1 << 22) - 1)
};

LSB 側から見て 8-13 ビット目は nw_src, 14-19 ビット目は nw_dst の wildcard を表しています。今回の例では nw_dst = 192.168.1.0/24 ですので wildcard として扱うのは下位 8 ビットです。そのため、14-19 ビット目が 001000b となっています。nw_src は 0.0.0.0/0 なので 32 ビット全てが wildcard となり、8-13 ビット目が 100000b つまり 32 となっています。

Ruby を使った場合この wildcard を気にする必要はありませんが、C 言語の場合は、適切な値に設定する必要があります。次回は、この点に注意して C 言語で Match を書く方法について、説明します。