{
    "mode": "man",
    "parameter": "tc-pedit",
    "section": "8",
    "url": "https://www.chedong.com/phpMan.php/man/tc-pedit/8/json",
    "generated": "2026-06-14T07:35:58Z",
    "synopsis": "tc ... action pedit [ex] munge { RAWOP | LAYEREDOP | EXTENDEDLAYEREDOP } [ CONTROL ]\nRAWOP := offset OFFSET { u8 | u16 | u32 } [ ATSPEC ] CMDSPEC\nATSPEC := at AT offmask MASK shift SHIFT\nLAYEREDOP := { ip IPHDRFIELD | ip BEYONDIPHDRFIELD } CMDSPEC\nEXTENDEDLAYEREDOP  :=  {  eth  ETHHDRFIELD  |  ip  IPHDRFIELD  |  ip EXIPHDRFIELD | ip6\nIP6HDRFIELD | tcp TCPHDRFIELD | udp UDPHDRFIELD } CMDSPEC\nETHHDRFIELD := { src | dst | type }\nIPHDRFIELD := { src | dst | tos | dsfield | ihl | protocol | precedence | nofrag | firstfrag\n| ce | df }\nBEYONDIPHDRFIELD := { dport | sport | icmptype | icmpcode }\nEXIPHDRFIELD := { ttl }\nIP6HDRFIELD := { src | dst | trafficclass | flowlbl | payloadlen | nexthdr | hoplimit }\nTCPHDRFIELD := { sport | dport | flags }\nUDPHDRFIELD := { sport | dport }\nCMDSPEC := { clear | invert | set VAL | add VAL | decrement | preserve } [ retain RVAL ]\nCONTROL := { reclassify | pipe | drop | shot | continue | pass | goto chain CHAININDEX }",
    "sections": {
        "NAME": {
            "content": "pedit - generic packet editor action\n",
            "subsections": []
        },
        "SYNOPSIS": {
            "content": "tc ... action pedit [ex] munge { RAWOP | LAYEREDOP | EXTENDEDLAYEREDOP } [ CONTROL ]\n\nRAWOP := offset OFFSET { u8 | u16 | u32 } [ ATSPEC ] CMDSPEC\n\nATSPEC := at AT offmask MASK shift SHIFT\n\nLAYEREDOP := { ip IPHDRFIELD | ip BEYONDIPHDRFIELD } CMDSPEC\n\nEXTENDEDLAYEREDOP  :=  {  eth  ETHHDRFIELD  |  ip  IPHDRFIELD  |  ip EXIPHDRFIELD | ip6\nIP6HDRFIELD | tcp TCPHDRFIELD | udp UDPHDRFIELD } CMDSPEC\n\nETHHDRFIELD := { src | dst | type }\n\nIPHDRFIELD := { src | dst | tos | dsfield | ihl | protocol | precedence | nofrag | firstfrag\n| ce | df }\n\nBEYONDIPHDRFIELD := { dport | sport | icmptype | icmpcode }\n\nEXIPHDRFIELD := { ttl }\n\n\nIP6HDRFIELD := { src | dst | trafficclass | flowlbl | payloadlen | nexthdr | hoplimit }\n\nTCPHDRFIELD := { sport | dport | flags }\n\nUDPHDRFIELD := { sport | dport }\n\nCMDSPEC := { clear | invert | set VAL | add VAL | decrement | preserve } [ retain RVAL ]\n\nCONTROL := { reclassify | pipe | drop | shot | continue | pass | goto chain CHAININDEX }\n",
            "subsections": []
        },
        "DESCRIPTION": {
            "content": "The  pedit action can be used to change arbitrary packet data. The location of data to change\ncan either be specified by giving an offset and size as in RAWOP, or for  header  values  by\nnaming the header and field to edit the size is then chosen automatically based on the header\nfield size.\n",
            "subsections": []
        },
        "OPTIONS": {
            "content": "ex     Use extended pedit.  EXTENDEDLAYEREDOP and the add/decrement  CMDSPEC  are  allowed\nonly in this mode.\n\noffset OFFSET { u32 | u16 | u8 }\nSpecify  the offset at which to change data.  OFFSET is a signed integer, it's base is\nautomatically chosen (e.g. hex if prefixed by 0x or octal if prefixed by 0).  The sec‐\nond  argument  specifies  the  length of data to change, that is four bytes (u32), two\nbytes (u16) or a single byte (u8).\n\nat AT offmask MASK shift SHIFT\nThis is an optional part of RAWOP which allows to have a variable OFFSET depending on\npacket  data  at offset AT, which is binary ANDed with MASK and right-shifted by SHIFT\nbefore adding it to OFFSET.\n\neth ETHHDRFIELD\nChange an ETH header field. The supported keywords for ETHHDRFIELD are:\n\nsrc\ndst    Source or destination MAC address in the standard format: XX:XX:XX:XX:XX:XX\n\ntype   Ether-type in numeric value\n\nip IPHDRFIELD\nChange an IPv4 header field. The supported keywords for IPHDRFIELD are:\n\nsrc\ndst    Source or destination IP address, a four-byte value.\n\ntos\ndsfield\nprecedence\nType Of Service field, an eight-bit value.\n\nihl    Change the IP Header Length field, a four-bit value.\n\nprotocol\nNext-layer Protocol field, an eight-bit value.\n\nnofrag\nfirstfrag\nce\ndf\nmf     Change IP header flags. Note that the value to pass to the set command  is  not\njust a bit value, but the full byte including the flags field.  Though only the\nrelevant bits of that value are respected, the rest ignored.\n\nip BEYONDIPHDRFIELD\nSupported only for non-extended layered op. It is passed to the kernel as offsets rel‐\native  to  the beginning of the IP header and assumes the IP header is of minimum size\n(20 bytes). The supported keywords for BEYONDIPHDRFIELD are:\n\ndport\nsport  Destination or source port numbers, a 16-bit value. Indeed, IPv4 headers  don't\ncontain this information. Instead, this will set an offset which suits at least\nTCP and UDP if the IP header is of minimum size (20 bytes). If not,  this  will\ndo unexpected things.\n\nicmptype\nicmpcode\nAgain,  this allows to change data past the actual IP header itself. It assumes\nan ICMP header is present immediately following the (minimal sized) IP  header.\nIf it is not or the latter is bigger than the minimum of 20 bytes, this will do\nunexpected things. These fields are eight-bit values.\n\nip EXIPHDRFIELD\nSupported only when ex is used. The supported keywords for EXIPHDRFIELD are:\n\nttl\n\nip6 IP6HDRFIELD\nThe supported keywords for IP6HDRFIELD are:\n\nsrc\ndst\ntrafficclass\nflowlbl\npayloadlen\nnexthdr\nhoplimit\n\ntcp TCPHDRFIELD\nThe supported keywords for TCPHDRFIELD are:\n\nsport\ndport  Source or destination TCP port number, a 16-bit value.\n\nflags\n\nudp UDPHDRFIELD\nThe supported keywords for UDPHDRFIELD are:\n\nsport\ndport  Source or destination TCP port number, a 16-bit value.\n\nclear  Clear the addressed data (i.e., set it to zero).\n\ninvert Swap every bit in the addressed data.\n\nset VAL\nSet the addressed data to a specific value. The size of VAL is defined by  either  one\nof the u32, u16 or u8 keywords in RAWOP, or the size of the addressed header field in\nLAYEREDOP.\n\nadd VAL\nAdd the addressed data by a specific value. The size of VAL is defined by the size  of\nthe  addressed  header field in EXTENDEDLAYEREDOP.  This operation is supported only\nfor extended layered op.\n",
            "subsections": [
                {
                    "name": "decrement",
                    "content": "Decrease the addressed data by one.  This operation is supported only for ip  ttl  and\nip6 hoplimit.\n"
                },
                {
                    "name": "preserve",
                    "content": "Keep the addressed data as is.\n\nretain RVAL\nThis  optional  extra part of CMDSPEC allows to exclude bits from being changed. Sup‐\nported only for 32 bits fields or smaller.\n\nCONTROL\nThe following keywords allow to control how the tree of qdisc,  classes,  filters  and\nactions is further traversed after this action.\n\nreclassify\nRestart with the first filter in the current list.\n\npipe   Continue with the next action attached to the same filter.\n\ndrop\nshot   Drop the packet.\n\ncontinue\nContinue classification with the next filter in line.\n\npass   Finish  classification  process  and return to calling qdisc for further packet\nprocessing. This is the default.\n"
                }
            ]
        },
        "EXAMPLES": {
            "content": "Being able to edit packet data, one could do all kinds of things, such as e.g.   implementing\nport redirection. Certainly not the most useful application, but as an example it should do:\n\nFirst,  qdiscs need to be set up to attach filters to. For the receive path, a simple ingress\nqdisc will do, for transmit path a classful qdisc (HTB in this case) is necessary:\n\ntc qdisc replace dev eth0 root handle 1: htb\ntc qdisc add dev eth0 ingress handle ffff:\n\nFinally, a filter with pedit action can be added for each direction. In  this  case,  u32  is\nused  matching  on the port number to redirect from, while pedit then does the actual rewrit‐\ning:\n\ntc filter add dev eth0 parent 1: u32 \\\nmatch ip dport 23 0xffff \\\naction pedit pedit munge ip dport set 22\ntc filter add dev eth0 parent ffff: u32 \\\nmatch ip sport 22 0xffff \\\naction pedit pedit munge ip sport set 23\ntc filter add dev eth0 parent ffff: u32 \\\nmatch ip sport 22 0xffff \\\naction pedit ex munge ip dst set 192.168.1.199\ntc filter add dev eth0 parent ffff: u32 \\\nmatch ip sport 22 0xffff \\\naction pedit ex munge ip6 dst set fe80::dacb:8aff:fec7:320e\ntc filter add dev eth0 parent ffff: u32 \\\nmatch ip sport 22 0xffff \\\naction pedit ex munge eth dst set 11:22:33:44:55:66\ntc filter add dev eth0 parent ffff: u32 \\\nmatch ip dport 23 0xffff \\\naction pedit ex munge tcp dport set 22\n\nTo rewrite just part of a field, use the retain directive. E.g. to overwrite the DSCP part of\na dsfield with $DSCP, without touching ECN:\n\ntc filter add dev eth0 ingress flower ... \\\naction pedit ex munge ip dsfield set $((DSCP << 2)) retain 0xfc\n\nAnd vice versa, to set ECN to e.g. 1 without impacting DSCP:\n\ntc filter add dev eth0 ingress flower ... \\\naction pedit ex munge ip dsfield set 1 retain 0x3\n\n",
            "subsections": []
        },
        "SEE ALSO": {
            "content": "tc(8), tc-htb(8), tc-u32(8)\n\n\n\niproute2                                     12 Jan 2015       Generic packet editor action in tc(8)",
            "subsections": []
        }
    },
    "summary": "pedit - generic packet editor action",
    "flags": [],
    "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: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": [
        {
            "name": "tc",
            "section": "8",
            "url": "https://www.chedong.com/phpMan.php/man/tc/8/json"
        },
        {
            "name": "tc-htb",
            "section": "8",
            "url": "https://www.chedong.com/phpMan.php/man/tc-htb/8/json"
        },
        {
            "name": "tc-u32",
            "section": "8",
            "url": "https://www.chedong.com/phpMan.php/man/tc-u32/8/json"
        },
        {
            "name": "tc",
            "section": "8",
            "url": "https://www.chedong.com/phpMan.php/man/tc/8/json"
        }
    ]
}