# man > tc-pedit(8)

Generic packet editor action in [tc(8)](https://www.chedong.com/phpMan.php/man/tc/8/markdown)           Linux          Generic packet editor action in [tc(8)](https://www.chedong.com/phpMan.php/man/tc/8/markdown)



## 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 sec‐
              ond  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 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 rel‐
              ative  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 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 to exclude bits from being changed. Sup‐
              ported only for 32 bits fields or smaller.

       _CONTROL_
              The following keywords allow 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 rewrit‐
       ing:

              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](https://www.chedong.com/phpMan.php/perldoc/fe80%3A%3Adacb/markdown):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


## SEE ALSO
       [**tc**(8)](https://www.chedong.com/phpMan.php/man/tc/8/markdown), [**tc-htb**(8)](https://www.chedong.com/phpMan.php/man/tc-htb/8/markdown), [**tc-u32**(8)](https://www.chedong.com/phpMan.php/man/tc-u32/8/markdown)



iproute2                                     12 Jan 2015       Generic packet editor action in [tc(8)](https://www.chedong.com/phpMan.php/man/tc/8/markdown)
