Save this information when we checkpoint an skb and provide a mechanism to restore that information on restart. This will be used in the subsequent INET patch. Signed-off-by: Dan Smith <danms@xxxxxxxxxx> Changes in v2: - Add range checks to ensure that the header marks we restore are within the data length of the skb --- include/linux/checkpoint.h | 2 + include/linux/checkpoint_hdr.h | 7 ++++++ net/checkpoint.c | 45 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 0 deletions(-) diff --git a/include/linux/checkpoint.h b/include/linux/checkpoint.h index 4b61378..c2832ac 100644 --- a/include/linux/checkpoint.h +++ b/include/linux/checkpoint.h @@ -100,6 +100,8 @@ extern int ckpt_sock_getnames(struct ckpt_ctx *ctx, struct socket *socket, struct sockaddr *loc, unsigned *loc_len, struct sockaddr *rem, unsigned *rem_len); +int sock_restore_header_info(struct sk_buff *skb, + struct ckpt_hdr_socket_buffer *h); /* ckpt kflags */ #define ckpt_set_ctx_kflag(__ctx, __kflag) \ diff --git a/include/linux/checkpoint_hdr.h b/include/linux/checkpoint_hdr.h index ca2500d..3e6cab1 100644 --- a/include/linux/checkpoint_hdr.h +++ b/include/linux/checkpoint_hdr.h @@ -542,8 +542,15 @@ struct ckpt_hdr_socket_queue { struct ckpt_hdr_socket_buffer { struct ckpt_hdr h; + __u64 mac_len; + __u64 hdr_len; + __u64 transport_header; + __u64 network_header; + __u64 mac_header; __s32 sk_objref; __s32 pr_objref; + __u16 protocol; + __u8 cb[48]; }; #define CKPT_UNIX_LINKED 1 diff --git a/net/checkpoint.c b/net/checkpoint.c index dd23efd..50baea9 100644 --- a/net/checkpoint.c +++ b/net/checkpoint.c @@ -88,6 +88,50 @@ static int sock_copy_buffers(struct sk_buff_head *from, return -EAGAIN; } +static void sock_record_header_info(struct sk_buff *skb, + struct ckpt_hdr_socket_buffer *h) +{ + + h->mac_len = skb->mac_len; + h->hdr_len = skb->hdr_len; + +#ifdef NET_SKBUFF_DATA_USES_OFFSET + h->transport_header = skb->transport_hdr; + h->network_header = skb->network_header; + h->mac_header = skb->mac_header; +#else + h->transport_header = skb->transport_header - skb->head; + h->network_header = skb->network_header - skb->head; + h->mac_header = skb->mac_header - skb->head; +#endif + + memcpy(h->cb, skb->cb, sizeof(skb->cb)); +} + +int sock_restore_header_info(struct sk_buff *skb, + struct ckpt_hdr_socket_buffer *h) +{ + if ((h->transport_header >= skb->len) || + (h->network_header >= skb->len) || + (h->mac_header >= skb->len) || + (h->mac_len >= skb->len) || + (h->hdr_len >= skb->len)) { + ckpt_debug("skb header positions not within data length\n"); + return -EINVAL; + } + + skb->mac_len = h->mac_len; + skb->hdr_len = h->hdr_len; + + skb_set_transport_header(skb, h->transport_header); + skb_set_network_header(skb, h->network_header); + skb_set_mac_header(skb, h->mac_header); + + memcpy(skb->cb, h->cb, sizeof(skb->cb)); + + return 0; +} + static int __sock_write_buffers(struct ckpt_ctx *ctx, struct sk_buff_head *queue, int dst_objref) @@ -123,6 +167,7 @@ static int __sock_write_buffers(struct ckpt_ctx *ctx, goto end; h->sk_objref = ret; h->pr_objref = dst_objref; + sock_record_header_info(skb, h); ret = ckpt_write_obj(ctx, (struct ckpt_hdr *) h); if (ret < 0) -- 1.6.2.5 _______________________________________________ Containers mailing list Containers@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/containers