# tc-pedit

## NAME



           pedit - generic packet editor action
    


## SYNOPSIS



           **tc**... **action pedit [ex] munge**{ _RAW_OP_ | _LAYERED_OP_ |
                   _EXTENDED_LAYERED_OP_ } [ _CONTROL_ ]
    
           _RAW_OP_ := **offset** _OFFSET_ { **u8** | **u16** | **u32**} [ _AT_SPEC_ ] _CMD_SPEC_
    
           _AT_SPEC_ := **at** _AT_ **offmask** _MASK_ **shift** _SHIFT_
    
           _LAYERED_OP_ := { **ip** _IPHDR_FIELD_ | **ip** _BEYOND_IPHDR_FIELD_ } _CMD_SPEC_
    
           _EXTENDED_LAYERED_OP_ := { **eth** _ETHHDR_FIELD_ | **ip** _IPHDR_FIELD_ | **ip**
                   _EX_IPHDR_FIELD_ | **ip6** _IP6HDR_FIELD_ | **tcp** _TCPHDR_FIELD_ | **udp**
                   _UDPHDR_FIELD_ } _CMD_SPEC_
    
           _ETHHDR_FIELD_ := { **src** | **dst** | **type**}
    
           _IPHDR_FIELD_ := { **src** | **dst** | **tos** | **dsfield** | **ihl** | **protocol** |
                   **precedence** | **nofrag** | **firstfrag** | **ce** | **df**}
    
           _BEYOND_IPHDR_FIELD_ := { **dport** | **sport** | **icmp_type** | **icmp_code**}
    
           _EX_IPHDR_FIELD_ := { **ttl**}
    
           _IP6HDR_FIELD_ := { **src** | **dst** | **traffic_class** | **flow_lbl** |
                   **payload_len** | **nexthdr** | **hoplimit**}
    
           _TCPHDR_FIELD_ := { **sport** | **dport** | **flags**}
    
           _UDPHDR_FIELD_ := { **sport** | **dport**}
    
           _CMD_SPEC_ := { **clear** | **invert** | **set** _VAL_ | **add** _VAL_ | **decrement** |
                   **preserve**} [ **retain** _RVAL_ ]
    
           _CONTROL_ := { **reclassify** | **pipe** | **drop** | **shot** | **continue** | **pass** |
                   **goto chain CHAIN_INDEX**}
    


## DESCRIPTION



           The **pedit** action can be used to change arbitrary packet data. The
           location of data to change can either be specified by giving an
           offset and size as in _RAW_OP_ , or for header values by naming the
           header and field to edit the size is then chosen automatically
           based on the header field size.
    


## OPTIONS



           **ex** Use extended pedit.  _EXTENDED_LAYERED_OP_ and the
                  add/decrement _CMD_SPEC_ are allowed only in this mode.
    
           **offset** _OFFSET_ { **u32** | **u16** | **u8**}
                  Specify the offset at which to change data.  _OFFSET_ is a
                  signed integer, it's base is automatically chosen (e.g. hex
                  if prefixed by **0x** or octal if prefixed by **0**).  The second
                  argument specifies the length of data to change, that is
                  four bytes (**u32**), two bytes (**u16**) or a single byte (**u8**).
    
           **at** _AT_ **offmask** _MASK_ **shift** _SHIFT_
                  This is an optional part of _RAW_OP_ which allows one to have
                  a variable _OFFSET_ depending on packet data at offset _AT_ ,
                  which is binary ANDed with _MASK_ and right-shifted by _SHIFT_
                  before adding it to _OFFSET_.
    
           **eth** _ETHHDR_FIELD_
                  Change an ETH header field. The supported keywords for
                  _ETHHDR_FIELD_ are:
    
                  **src**
                  **dst** Source or destination MAC address in the standard
                         format: XX:XX:XX:XX:XX:XX
    
                  **type** Ether-type in numeric value
    
           **ip** _IPHDR_FIELD_
                  Change an IPv4 header field. The supported keywords for
                  _IPHDR_FIELD_ are:
    
                  **src**
                  **dst** Source or destination IP address, a four-byte value.
    
                  **tos**
                  **dsfield**
                  **precedence**
                         Type Of Service field, an eight-bit value.
    
                  **ihl** Change the IP Header Length field, a four-bit value.
    
                  **protocol**
                         Next-layer Protocol field, an eight-bit value.
    
                  **nofrag**
                  **firstfrag**
                  **ce**
                  **df**
                  **mf** Change IP header flags. Note that the value to pass
                         to the **set** command is not just a bit value, but the
                         full byte including the flags field.  Though only
                         the relevant bits of that value are respected, the
                         rest ignored.
    
           **ip** _BEYOND_IPHDR_FIELD_
                  Supported only for non-extended layered op. It is passed to
                  the kernel as offsets relative to the beginning of the IP
                  header and assumes the IP header is of minimum size (20
                  bytes). The supported keywords for _BEYOND_IPHDR_FIELD_ are:
    
                  **dport**
                  **sport** Destination or source port numbers, a 16-bit value.
                         Indeed, IPv4 headers don't contain this information.
                         Instead, this will set an offset which suits at
                         least TCP and UDP if the IP header is of minimum
                         size (20 bytes). If not, this will do unexpected
                         things.
    
                  **icmp_type**
                  **icmp_code**
                         Again, this allows one to change data past the
                         actual IP header itself. It assumes an ICMP header
                         is present immediately following the (minimal sized)
                         IP header.  If it is not or the latter is bigger
                         than the minimum of 20 bytes, this will do
                         unexpected things. These fields are eight-bit
                         values.
    
           **ip** _EX_IPHDR_FIELD_
                  Supported only when _ex_ is used. The supported keywords for
                  _EX_IPHDR_FIELD_ are:
    
                  **ttl**
    
           **ip6** _IP6HDR_FIELD_
                  The supported keywords for _IP6HDR_FIELD_ are:
    
                  **src**
                  **dst**
                  **traffic_class**
                  **flow_lbl**
                  **payload_len**
                  **nexthdr**
                  **hoplimit**
    
           **tcp** _TCPHDR_FIELD_
                  The supported keywords for _TCPHDR_FIELD_ are:
    
                  **sport**
                  **dport** Source or destination TCP port number, a 16-bit
                         value.
    
                  **flags**
    
           **udp** _UDPHDR_FIELD_
                  The supported keywords for _UDPHDR_FIELD_ are:
    
                  **sport**
                  **dport** Source or destination TCP port number, a 16-bit
                         value.
    
           **clear** Clear the addressed data (i.e., set it to zero).
    
           **invert** Swap every bit in the addressed data.
    
           **set** _VAL_
                  Set the addressed data to a specific value. The size of _VAL_
                  is defined by either one of the **u32** , **u16** or **u8** keywords in
                  _RAW_OP_ , or the size of the addressed header field in
                  _LAYERED_OP_.
    
           **add** _VAL_
                  Add the addressed data by a specific value. The size of _VAL_
                  is defined by the size of the addressed header field in
                  _EXTENDED_LAYERED_OP_.  This operation is supported only for
                  extended layered op.
    
           **decrement**
                  Decrease the addressed data by one.  This operation is
                  supported only for **ip ttl** and **ip6 hoplimit**.
    
           **preserve**
                  Keep the addressed data as is.
    
           **retain** _RVAL_
                  This optional extra part of _CMD_SPEC_ allows one to exclude
                  bits from being changed. Supported only for 32 bits fields
                  or smaller.
    
           _CONTROL_
                  The following keywords allow one to control how the tree of
                  qdisc, classes, filters and actions is further traversed
                  after this action.
    
                  **reclassify**
                         Restart with the first filter in the current list.
    
                  **pipe** Continue with the next action attached to the same
                         filter.
    
                  **drop**
                  **shot** Drop the packet.
    
                  **continue**
                         Continue classification with the next filter in
                         line.
    
                  **pass** Finish classification process and return to calling
                         qdisc for further packet processing. This is the
                         default.
    


## EXAMPLES



           Being able to edit packet data, one could do all kinds of things,
           such as e.g.  implementing port redirection. Certainly not the
           most useful application, but as an example it should do:
    
           First, qdiscs need to be set up to attach filters to. For the
           receive path, a simple **ingress** qdisc will do, for transmit path a
           classful qdisc (**HTB** in this case) is necessary:
    
                  tc qdisc replace dev eth0 root handle 1: htb
                  tc qdisc add dev eth0 ingress handle ffff:
    
           Finally, a filter with **pedit** action can be added for each
           direction. In this case, **u32** is used matching on the port number
           to redirect from, while **pedit** then does the actual rewriting:
    
                  tc filter add dev eth0 parent 1: u32 \
                       match ip dport 23 0xffff \
                       action pedit pedit munge ip dport set 22
                  tc filter add dev eth0 parent ffff: u32 \
                       match ip sport 22 0xffff \
                       action pedit pedit munge ip sport set 23
                  tc filter add dev eth0 parent ffff: u32 \
                       match ip sport 22 0xffff \
                       action pedit ex munge ip dst set 192.168.1.199
                  tc filter add dev eth0 parent ffff: u32 \
                       match ip sport 22 0xffff \
                       action pedit ex munge ip6 dst set fe80::dacb:8aff:fec7:320e
                  tc filter add dev eth0 parent ffff: u32 \
                       match ip sport 22 0xffff \
                       action pedit ex munge eth dst set 11:22:33:44:55:66
                  tc filter add dev eth0 parent ffff: u32 \
                       match ip dport 23 0xffff \
                       action pedit ex munge tcp dport set 22
    
           To rewrite just part of a field, use the **retain** directive. E.g. to
           overwrite the DSCP part of a dsfield with $DSCP, without touching
           ECN:
    
                  tc filter add dev eth0 ingress flower ... \
                       action pedit ex munge ip dsfield set $((DSCP << 2)) retain 0xfc
    
           And vice versa, to set ECN to e.g. 1 without impacting DSCP:
    
                  tc filter add dev eth0 ingress flower ... \
                       action pedit ex munge ip dsfield set 1 retain 0x3
    


* * *