diff --git a/scapy/fields.py b/scapy/fields.py
index cecd8761ae56e84fd1bb59c23f96386794969cc8..d4e5f4caff0d7695732868366c87cedbf9beca23 100644
--- a/scapy/fields.py
+++ b/scapy/fields.py
@@ -26,6 +26,7 @@ class Field(object):
     __slots__ = ["name", "fmt", "default", "sz", "owners"]
     __metaclass__ = Field_metaclass
     islist = 0
+    ismutable = False
     holds_packets = 0
     def __init__(self, name, default, fmt="H"):
         self.name = name
@@ -1008,6 +1009,8 @@ class FlagValue(object):
                 self.value &= ~(2 ** self.names.index(attr))
         else:
             return super(FlagValue, self).__setattr__(attr, value)
+    def copy(self):
+        return self.__class__(self.value, self.names)
 
 
 class FlagsField(BitField):
@@ -1031,6 +1034,7 @@ class FlagsField(BitField):
    :param size: number of bits in the field
    :param names: (list or dict) label for each flag, Least Significant Bit tag's name is written first
    """
+    ismutable = True
     __slots__ = ["multi", "names"]
     def __init__(self, name, default, size, names):
         self.multi = isinstance(names, list)
@@ -1041,6 +1045,11 @@ class FlagsField(BitField):
             return type(x)(None if v is None else FlagValue(v, self.names)
                            for v in x)
         return None if x is None else FlagValue(x, self.names)
+    def m2i(self, pkt, x):
+        if isinstance(x, (list, tuple)):
+            return type(x)(None if v is None else FlagValue(v, self.names)
+                           for v in x)
+        return None if x is None else FlagValue(x, self.names)
     def i2repr(self, pkt, x):
         if isinstance(x, (list, tuple)):
             return repr(type(x)(
diff --git a/scapy/packet.py b/scapy/packet.py
index e2935ddb9fbe1baa2fdd4863a0bf9e1c98484a42..9a6d73ecee54e47f211201ca20ba894e40cfe8c1 100644
--- a/scapy/packet.py
+++ b/scapy/packet.py
@@ -589,7 +589,7 @@ Creates an EPS file describing a packet. If filename is not provided a temporary
             s, fval = f.getfield(self, s)
             # We need to track fields with mutable values to discard
             # .raw_packet_cache when needed.
-            if f.islist or f.holds_packets:
+            if f.islist or f.holds_packets or f.ismutable:
                 self.raw_packet_cache_fields[f.name] = f.do_copy(fval)
             self.fields[f.name] = fval
         assert(raw.endswith(s))
diff --git a/test/regression.uts b/test/regression.uts
index 393df949434fcc052efd761c21e9f63aaa34fc82..b87cfb8a7f67bcb68dd97169f609c64592c5e2b6 100644
--- a/test/regression.uts
+++ b/test/regression.uts
@@ -7532,3 +7532,27 @@ assert not any(getattr(pkt.flags, f) for f in 'FSRECN')
 pkt.flags = 50
 assert all(getattr(pkt.flags, f) for f in 'SAU')
 assert not any(getattr(pkt.flags, f) for f in 'FRPECN')
+
+= Flag values mutation with .raw_packet_cache
+~ IP TCP
+
+pkt = IP(str(IP(flags="MF")/TCP(flags="SA")))
+assert pkt.raw_packet_cache is not None
+assert pkt[TCP].raw_packet_cache is not None
+assert pkt.flags.MF
+assert not pkt.flags.DF
+assert not pkt.flags.evil
+assert pkt[TCP].flags.S
+assert pkt[TCP].flags.A
+assert not any(getattr(pkt[TCP].flags, f) for f in 'FRPUECN')
+pkt.flags.MF = 0
+pkt.flags.DF = 1
+pkt[TCP].flags.U = True
+pkt[TCP].flags.S = False
+pkt = IP(str(pkt))
+assert not pkt.flags.MF
+assert pkt.flags.DF
+assert not pkt.flags.evil
+assert pkt[TCP].flags.A
+assert pkt[TCP].flags.U
+assert not any(getattr(pkt[TCP].flags, f) for f in 'FSRPECN')