+ struct udphdr *th;
+ __sum16 *check;
+ __be16 *port;
+
+ if (unlikely(!is_ip(skb, key)))
+ return skb;
+
+ skb = make_writable(skb, 0, gfp);
+ if (unlikely(!skb))
+ return NULL;
+
+ /* Must follow make_writable() since that can move the skb data. */
+ check = get_l4_checksum(skb, key);
+ if (unlikely(!check))
+ return skb;
+
+ /*
+ * Update port and checksum.
+ *
+ * This is OK because source and destination port numbers are at the
+ * same offsets in both UDP and TCP headers, and get_l4_checksum() only
+ * supports those protocols.
+ */
+ th = udp_hdr(skb);
+ port = a->type == ODPAT_SET_TP_SRC ? &th->source : &th->dest;
+ update_csum(check, skb, *port, a->tp_port, 0);
+ *port = a->tp_port;
+
+ return skb;