{
    "mode": "man",
    "parameter": "tc-pedit",
    "section": "8",
    "url": "https://www.chedong.com/phpMan.php/man/tc-pedit/8/json",
    "generated": "2026-08-18T15:23:08Z",
    "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 one to have a variable OFFSET depend‐\ning on packet data at offset AT, which is binary ANDed with MASK and right-shifted  by\nSHIFT before 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 one to change data past the actual IP header itself. It as‐\nsumes an ICMP header is present immediately following the  (minimal  sized)  IP\nheader.   If  it  is  not or the latter is bigger than the minimum of 20 bytes,\nthis will do unexpected 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 one to exclude bits  from  being  changed.\nSupported only for 32 bits fields or smaller.\n\nCONTROL\nThe  following  keywords  allow one to control how the tree of qdisc, classes, filters\nand actions 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\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"
        }
    ]
}