P4中的寄存器、计量器、计数器学习

计数器

CounterType

enum CounterType {
    packets,
    bytes,
    packets_and_bytes
}
extern counter
#if V1MODEL_VERSION >= 20200408
<I>
#endif
{
    /***
     * A counter object is created by calling its constructor.  This
     * creates an array of counter states, with the number of counter
     * states specified by the size parameter.  The array indices are
     * in the range [0, size-1].
     *
     * You must provide a choice of whether to maintain only a packet
     * count (CounterType.packets), only a byte count
     * (CounterType.bytes), or both (CounterType.packets_and_bytes).
     *
     * Counters can be updated from your P4 program, but can only be
     * read from the control plane.  If you need something that can be
     * both read and written from the P4 program, consider using a
     * register.
     */
    counter(bit<32> size, CounterType type);
    // FIXME -- size arg should be `int` but that breaks typechecking

    /***
     * count() causes the counter state with the specified index to be
     * read, modified, and written back, atomically relative to the
     * processing of other packets, updating the packet count, byte
     * count, or both, depending upon the CounterType of the counter
     * instance used when it was constructed.
     *
     * @param index The index of the counter state in the array to be
     *              updated, normally a value in the range [0,
     *              size-1].  If index >= size, no counter state will be
     *              updated.
     */
#if V1MODEL_VERSION >= 20200408
    void count(in I index);
#else
    void count(in bit<32> index);
#endif
}

extern direct_counter {
    /***
     * A direct_counter object is created by calling its constructor.
     * You must provide a choice of whether to maintain only a packet
     * count (CounterType.packets), only a byte count
     * (CounterType.bytes), or both (CounterType.packets_and_bytes).
     * After constructing the object, you can associate it with at
     * most one table, by adding the following table property to the
     * definition of that table:
     *
     *     counters = <object_name>;
     *
     * Counters can be updated from your P4 program, but can only be
     * read from the control plane.  If you need something that can be
     * both read and written from the P4 program, consider using a
     * register.
     */
    direct_counter(CounterType type);
    /***
     * The count() method is actually unnecessary in the v1model
     * architecture.  This is because after a direct_counter object
     * has been associated with a table as described in the
     * documentation for the direct_counter constructor, every time
     * the table is applied and a table entry is matched, the counter
     * state associated with the matching entry is read, modified, and
     * written back, atomically relative to the processing of other
     * packets, regardless of whether the count() method is called in
     * the body of that action.
     */
    void count();
}

#define V1MODEL_METER_COLOR_GREEN  0
#define V1MODEL_METER_COLOR_YELLOW 1
#define V1MODEL_METER_COLOR_RED    2

1)可以选择对数据包计数或对字节计数或二者都进行
2)可以在P4中更新计数器,但是在控制平面只能对计数器进行读操作;
如果想在P4程序中同时进行读、写,那么可以考虑通过寄存器实现

计量器

enum MeterType {
    packets,
    bytes
}
extern meter
#if V1MODEL_VERSION >= 20200408
<I>
#endif
{
    /***
     * A meter object is created by calling its constructor.  This
     * creates an array of meter states, with the number of meter
     * states specified by the size parameter.  The array indices are
     * in the range [0, size-1].  For example, if in your system you
     * have 128 different "flows" numbered from 0 up to 127, and you
     * want to meter each of those flows independently of each other,
     * you could do so by creating a meter object with size=128.
     *
     * You must provide a choice of whether to meter based on the
     * number of packets, regardless of their size
     * (MeterType.packets), or based upon the number of bytes the
     * packets contain (MeterType.bytes).
     */
    meter(bit<32> size, MeterType type);
    // FIXME -- size arg should be `int` but that breaks typechecking

    /***
     * execute_meter() causes the meter state with the specified index
     * to be read, modified, and written back, atomically relative to
     * the processing of other packets, and an integer encoding of one
     * of the colors green, yellow, or red to be written to the result
     * out parameter.
     *
     * @param index The index of the meter state in the array to be
     *              updated, normally a value in the range [0,
     *              size-1].  If index >= size, no meter state will be
     *              updated.
     * @param result Type T must be bit<W> with W >= 2.  When index is
     *              in range, the value of result will be assigned 0
     *              for color GREEN, 1 for color YELLOW, and 2 for
     *              color RED (see RFC 2697 and RFC 2698 for the
     *              meaning of these colors).  When index is out of
     *              range, the final value of result is not specified,
     *              and should be ignored by the caller.
     */
#if V1MODEL_VERSION >= 20200408
    void execute_meter<T>(in I index, out T result);
#else
    void execute_meter<T>(in bit<32> index, out T result);
#endif
}

extern direct_meter<T> {
    /***
     * A direct_meter object is created by calling its constructor.
     * You must provide a choice of whether to meter based on the
     * number of packets, regardless of their size
     * (MeterType.packets), or based upon the number of bytes the
     * packets contain (MeterType.bytes).  After constructing the
     * object, you can associate it with at most one table, by adding
     * the following table property to the definition of that table:
     *
     *     meters = <object_name>;
     */
    direct_meter(MeterType type);
    /***
     * After a direct_meter object has been associated with a table as
     * described in the documentation for the direct_meter
     * constructor, every time the table is applied and a table entry
     * is matched, the meter state associated with the matching entry
     * is read, modified, and written back, atomically relative to the
     * processing of other packets, regardless of whether the read()
     * method is called in the body of that action.
     *
     * read() may only be called within an action executed as a result
     * of matching a table entry, of a table that has a direct_meter
     * associated with it.  Calling read() causes an integer encoding
     * of one of the colors green, yellow, or red to be written to the
     * result out parameter.
     *
     * @param result Type T must be bit<W> with W >= 2.  The value of
     *              result will be assigned 0 for color GREEN, 1 for
     *              color YELLOW, and 2 for color RED (see RFC 2697
     *              and RFC 2698 for the meaning of these colors).
     */
    void read(out T result);
}

image

  • 比如说我们的系统有128条flow,我们想去计量每一条flow,那么我们就可以创建一个大小为128的计量器
  • size需要在int范围内
  • 可以选择类型,对数据包、字节进行计数

执行meter
image

  • 这个操作是对特定的下标的计量器进行读、修改、回写等操作
  • 根据result out 参数会有一个整数代表着绿色、黄色、红色
    参数T 是一个bit参数,W需要大于2,当index在这个范围内,result将会被置为0(green)、1(yellow)、2(red),index超出range,就会被忽略

image

direct_meter 可以和一个table相关联,每当table被调用并且有一个表条目匹配
image

只有和direct_meter相关联的table才能调用read(),这个调用将会给result一个值,代表着GREEN、YELLOW、RED

寄存器

#if V1MODEL_VERSION >= 20200408
extern register<T, I>
#else
extern register<T>
#endif
{
    /***
     * A register object is created by calling its constructor.  This
     * creates an array of 'size' identical elements, each with type
     * T.  The array indices are in the range [0, size-1].  For
     * example, this constructor call:
     *
     *     register<bit<32>>(512) my_reg;
     *
     * allocates storage for 512 values, each with type bit<32>.
     */
    register(bit<32> size);  // FIXME -- arg should be `int` but that breaks typechecking
    /***
     * read() reads the state of the register array stored at the
     * specified index, and returns it as the value written to the
     * result parameter.
     *
     * @param index The index of the register array element to be
     *              read, normally a value in the range [0, size-1].
     * @param result Only types T that are bit<W> are currently
     *              supported.  When index is in range, the value of
     *              result becomes the value read from the register
     *              array element.  When index >= size, the final
     *              value of result is not specified, and should be
     *              ignored by the caller.
     */
    @noSideEffects
#if V1MODEL_VERSION >= 20200408
    void read(out T result, in I index);
#else
    void read(out T result, in bit<32> index);
#endif
    /***
     * write() writes the state of the register array at the specified
     * index, with the value provided by the value parameter.
     *
     * If you wish to perform a read() followed later by a write() to
     * the same register array element, and you wish the
     * read-modify-write sequence to be atomic relative to other
     * processed packets, then there may be parallel implementations
     * of the v1model architecture for which you must execute them in
     * a P4_16 block annotated with an @atomic annotation.  See the
     * P4_16 language specification description of the @atomic
     * annotation for more details.
     *
     * @param index The index of the register array element to be
     *              written, normally a value in the range [0,
     *              size-1].  If index >= size, no register state will
     *              be updated.
     * @param value Only types T that are bit<W> are currently
     *              supported.  When index is in range, this
     *              parameter's value is written into the register
     *              array element specified by index.
     */
#if V1MODEL_VERSION >= 20200408
    void write(in I index, in T value);
#else
    void write(in bit<32> index, in T value);
#endif
}

posted @ 2022-05-14 13:40  盒什么饭  阅读(1174)  评论(0编辑  收藏  举报