* [RFC PATCH] IPVS: Backup, Adding IPv6 address packing
@ 2010-10-29 12:22 Hans Schillstrom
2010-10-30 6:53 ` Simon Horman
0 siblings, 1 reply; 4+ messages in thread
From: Hans Schillstrom @ 2010-10-29 12:22 UTC (permalink / raw)
To: lvs-devel, horms, ja, wensong, daniel.lezcano; +Cc: Hans Schillstrom
Add pack/unpack of IPv6 address in sync message
in binary form similar to the ASCII ::
A packed IPv6 address constists of -
first byte
high nibble first segment leng in bytes
low nibble possition of last segment.
then
First segemnt i.e. left side of ::
Last segment right side of ::
Examle FC00::2
unpacked FC00 0000 0000 0000 0000 0000 0000 0002
packed 1F FC02
Example 2 2003::2:100
unpacked 2003 0000 0000 0000 0000 0000 0002 0100
packed 2D 20 03 02 01 00
Signed-off-by: Hans Schillstrom <hans.schillstrom@ericsson.com>
---
net/netfilter/ipvs/ip_vs_sync.c | 128 +++++++++++++++++++++++++++++++++++---
1 files changed, 117 insertions(+), 11 deletions(-)
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index 00f0fd3..6b4976c 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -363,6 +363,65 @@ get_curr_sync_buff(unsigned long time)
return sb;
}
+/*
+ * Try to pack an IPv6 address
+ * Note that buffer must be at least 17 bytes
+ *
+ * Packing adds a byte before packed address
+ * m.s.nibble first segment size in bytes
+ * l.s.nibble last segment start offset in bytes (size = 16 - lastSeg)
+ *
+ * Return packed size, 0=no reduction
+ * buffer contains first/lastSegemnt + (un)packed address
+ *
+ */
+static int ipv6addr_pack(struct in6_addr *in6, char *buffer)
+{
+ int i, pos=0, score=0;
+ int lmatch=0, firstSeg=0,lastSeg=0;
+ char *addr = in6->s6_addr;
+ char *buff = buffer;
+
+ /* Check for more than 3 bytes of zeroes */
+ for( i=0; i<16; i++) {
+ if ( *(addr++) ) {
+ score = 0;
+ continue;
+ }
+ if ( !score )
+ pos = i;
+ score++;
+ if (score > lmatch) {
+ lmatch = score;
+ firstSeg = pos; /* Start of longest match */
+ }
+ }
+ lastSeg = firstSeg + lmatch;
+ addr = in6->s6_addr;
+ /* Store length of first seg then size of last seg */
+ *(buff++) = (firstSeg<<4 & 0xf0) | (lastSeg & 0xf);
+ memcpy(buff, addr, firstSeg); /* Copy first segment */
+ buff += firstSeg;
+ memcpy(buff, addr+lastSeg, 16-lastSeg);
+ return 16 - lmatch;
+}
+/*
+ * unpack IPv6 address packed by above func.
+ */
+static int ipv6addr_unpack(char *buff, struct in6_addr *addr)
+{
+ int firstSeg, lastSeg;
+
+ firstSeg = (*buff >> 4) & 0xf;
+ lastSeg = *(buff++) & 0xf;
+ addr->s6_addr32[0] = 0;
+ addr->s6_addr32[1] = 0;
+ addr->s6_addr32[2] = 0;
+ addr->s6_addr32[3] = 0;
+ memcpy(addr->s6_addr, buff, firstSeg);
+ memcpy(addr->s6_addr+lastSeg, buff+firstSeg, 16-lastSeg);
+ return 0;
+}
/*
* Add an ip_vs_conn information into the current sync_buff.
@@ -406,8 +465,8 @@ void ip_vs_sync_conn(struct ip_vs_conn *cp)
len += pe_name_len + 2;
len = (len+3) & 0xffc; /* Final 32 bit alignment */
- /* check if there is a space for this one */
- if (curr_sb && (curr_sb->head+len > curr_sb->end) ) {
+ /* check if there is a space for this one and offest for ipv6 pack*/
+ if (curr_sb && (curr_sb->head+len+4 > curr_sb->end) ) {
sb_queue_tail(curr_sb);
curr_sb = NULL;
}
@@ -441,10 +500,26 @@ void ip_vs_sync_conn(struct ip_vs_conn *cp)
#ifdef CONFIG_IP_VS_IPV6
if (cp->af == AF_INET6 ) {
- p += sizeof(struct ip_vs_sync_v6);
- ipv6_addr_copy(&s->v6.caddr, &cp->caddr.in6);
- ipv6_addr_copy(&s->v6.vaddr, &cp->vaddr.in6);
- ipv6_addr_copy(&s->v6.daddr, &cp->daddr.in6);
+ int psz;
+ p = (char *)&s->v6.caddr;
+ psz = ipv6addr_pack(&cp->caddr.in6, p);
+ psz += ipv6addr_pack(&cp->vaddr.in6, p+psz+1);
+ psz += ipv6addr_pack(&cp->vaddr.in6, p+psz+2);
+ if( psz >= 6 ) {
+ psz += 3;
+ p += psz;
+ s->v6.type |= STYPE_INET6_PACK;
+ len -= ((sizeof(struct in6_addr) * 3) - psz);
+ psz = sizeof(struct ip_vs_sync_v6)
+ - (sizeof(struct in6_addr) * 3) + psz;
+ s->v6.ver_size = htons(psz & SVER_MASK);
+ }
+ else {
+ p += sizeof(struct ip_vs_sync_v6);
+ ipv6_addr_copy(&s->v6.caddr, &cp->caddr.in6);
+ ipv6_addr_copy(&s->v6.vaddr, &cp->vaddr.in6);
+ ipv6_addr_copy(&s->v6.daddr, &cp->daddr.in6);
+ }
} else
#endif
{
@@ -508,13 +583,14 @@ ip_vs_conn_fill_param_sync(int af, union ip_vs_sync_conn *sc,
int pe_data_len, char *pe_name, int pe_name_len )
{
#ifdef CONFIG_IP_VS_IPV6
- if ( af == AF_INET6 )
- ip_vs_conn_fill_param(af, sc->v6.protocol,
+ if ( af == AF_INET6 ) {
+ if (!(sc->v6.type & STYPE_INET6_PACK))
+ ip_vs_conn_fill_param(af, sc->v6.protocol,
(const union nf_inet_addr *)&sc->v6.caddr,
sc->v6.cport,
(const union nf_inet_addr *)&sc->v6.vaddr,
sc->v6.vport, p);
- else
+ } else
#endif
ip_vs_conn_fill_param(af, sc->v4.protocol,
(const union nf_inet_addr *)&sc->v4.caddr,
@@ -780,7 +856,16 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen)
if (s->v6.type & STYPE_INET6 ) {
#ifdef CONFIG_IP_VS_IPV6
af = AF_INET6;
- p += sizeof(struct ip_vs_sync_v6);
+ if (s->v6.type & STYPE_INET6_PACK ) {
+ p = (char*) &s->v6.caddr;
+ p += 1 + ((*p >> 4) & 0xf) /* len + First seg */
+ + (16 - (*p & 0xf )); /* + Last seg */
+ p += 1 + ((*p >> 4) & 0xf) /* len + First seg */
+ + (16 - (*p & 0xf )); /* + Last seg */
+ p += 1 + ((*p >> 4) & 0xf) /* len + First seg */
+ + (16 - (*p & 0xf )); /* + Last seg */
+ } else
+ p += sizeof(struct ip_vs_sync_v6);
#else
IP_VS_DBG(2,"IPv6 sync message received, and IPVS is not compiled for IPv6\n");
p = (char *)s + size;
@@ -891,7 +976,27 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen)
? &opt : NULL),
pp);
#ifdef CONFIG_IP_VS_IPV6
- else
+ else {
+ /* Check if packed IPv6 */
+ if (s->v6.type & STYPE_INET6_PACK ) {
+ union nf_inet_addr vaddr, daddr, caddr;
+ int ret;
+ p = (char*) &s->v6.caddr;
+ ret = ipv6addr_unpack(p, &caddr.in6);
+ p += 1 + ((*p >> 4) & 0xf) + (16 - (*p & 0xf ));
+ ret |= ipv6addr_unpack(p, &vaddr.in6);
+ p += 1 + ((*p >> 4) & 0xf) + (16 - (*p & 0xf ));
+ ret |= ipv6addr_unpack(p, &daddr.in6);
+ if (ret) {
+ IP_VS_ERR_RL("Invalid packed IPv6 add in sync msg\n");
+ return;
+ }
+ ip_vs_conn_fill_param(af, s->v6.protocol,
+ &caddr, s->v6.cport,
+ &vaddr, s->v6.vport,
+ ¶m);
+
+ }
ip_vs_proc_conn(¶m, flags, state, s->v6.protocol,
af,
(union nf_inet_addr *)&s->v6.daddr,
@@ -900,6 +1005,7 @@ static void ip_vs_process_message(const char *buffer, const size_t buflen)
(opt_flags & IPVS_OPT_F_SEQ_DATA
? &opt : NULL),
pp);
+ }
#endif
p = (char *)s + size;
} /* End of for(...) */
--
1.7.0.1
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [RFC PATCH] IPVS: Backup, Adding IPv6 address packing
2010-10-29 12:22 [RFC PATCH] IPVS: Backup, Adding IPv6 address packing Hans Schillstrom
@ 2010-10-30 6:53 ` Simon Horman
2010-10-30 10:49 ` Hans Schillstrom
0 siblings, 1 reply; 4+ messages in thread
From: Simon Horman @ 2010-10-30 6:53 UTC (permalink / raw)
To: Hans Schillstrom; +Cc: lvs-devel, ja, wensong, daniel.lezcano
On Fri, Oct 29, 2010 at 02:22:00PM +0200, Hans Schillstrom wrote:
> Add pack/unpack of IPv6 address in sync message
> in binary form similar to the ASCII ::
>
> A packed IPv6 address constists of -
> first byte
> high nibble first segment leng in bytes
> low nibble possition of last segment.
> then
> First segemnt i.e. left side of ::
> Last segment right side of ::
>
> Examle FC00::2
> unpacked FC00 0000 0000 0000 0000 0000 0000 0002
> packed 1F FC02
> Example 2 2003::2:100
> unpacked 2003 0000 0000 0000 0000 0000 0002 0100
> packed 2D 20 03 02 01 00
Hi Hans,
are you sure the space saved is worth the additional complexity
that this patch introduces?
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [RFC PATCH] IPVS: Backup, Adding IPv6 address packing
2010-10-30 6:53 ` Simon Horman
@ 2010-10-30 10:49 ` Hans Schillstrom
2010-10-30 11:23 ` Simon Horman
0 siblings, 1 reply; 4+ messages in thread
From: Hans Schillstrom @ 2010-10-30 10:49 UTC (permalink / raw)
To: Simon Horman; +Cc: Hans Schillstrom, lvs-devel, ja, wensong, daniel.lezcano
On Saturday, October 30, 2010 08:53:03 Simon Horman wrote:
> On Fri, Oct 29, 2010 at 02:22:00PM +0200, Hans Schillstrom wrote:
> > Add pack/unpack of IPv6 address in sync message
> > in binary form similar to the ASCII ::
> >
> > A packed IPv6 address constists of -
> > first byte
> > high nibble first segment leng in bytes
> > low nibble possition of last segment.
> > then
> > First segemnt i.e. left side of ::
> > Last segment right side of ::
> >
> > Examle FC00::2
> > unpacked FC00 0000 0000 0000 0000 0000 0000 0002
> > packed 1F FC02
> > Example 2 2003::2:100
> > unpacked 2003 0000 0000 0000 0000 0000 0002 0100
> > packed 2D 20 03 02 01 00
>
> Hi Hans,
>
> are you sure the space saved is worth the additional complexity
> that this patch introduces?
> --
Hello Simon
I can see that my first mail 0/1 is still in my outbox.....
that mail contains just the question above and some calculations
My conclusion was that if you have 100M interface and a x64 CPU with a more optimized version
than it might be worth to pack the IPv6 Address.
On a 32bit CPU with 1G interfce the packing consume the same time that you might earn
The patch is just an example of how to do it,
Sorry for the confusion that I created without the [RFC PATCH 0/1]
The intension was to ask if anyone thinks that packing of IPv6 address should be there ?
I would say, much pain for little gain
Regards
Hans
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [RFC PATCH] IPVS: Backup, Adding IPv6 address packing
2010-10-30 10:49 ` Hans Schillstrom
@ 2010-10-30 11:23 ` Simon Horman
0 siblings, 0 replies; 4+ messages in thread
From: Simon Horman @ 2010-10-30 11:23 UTC (permalink / raw)
To: Hans Schillstrom; +Cc: Hans Schillstrom, lvs-devel, ja, wensong, daniel.lezcano
On Sat, Oct 30, 2010 at 12:49:19PM +0200, Hans Schillstrom wrote:
>
> On Saturday, October 30, 2010 08:53:03 Simon Horman wrote:
> > On Fri, Oct 29, 2010 at 02:22:00PM +0200, Hans Schillstrom wrote:
> > > Add pack/unpack of IPv6 address in sync message
> > > in binary form similar to the ASCII ::
> > >
> > > A packed IPv6 address constists of -
> > > first byte
> > > high nibble first segment leng in bytes
> > > low nibble possition of last segment.
> > > then
> > > First segemnt i.e. left side of ::
> > > Last segment right side of ::
> > >
> > > Examle FC00::2
> > > unpacked FC00 0000 0000 0000 0000 0000 0000 0002
> > > packed 1F FC02
> > > Example 2 2003::2:100
> > > unpacked 2003 0000 0000 0000 0000 0000 0002 0100
> > > packed 2D 20 03 02 01 00
> >
> > Hi Hans,
> >
> > are you sure the space saved is worth the additional complexity
> > that this patch introduces?
> > --
>
> Hello Simon
> I can see that my first mail 0/1 is still in my outbox.....
> that mail contains just the question above and some calculations
>
> My conclusion was that if you have 100M interface and a x64 CPU with a more optimized version
> than it might be worth to pack the IPv6 Address.
> On a 32bit CPU with 1G interfce the packing consume the same time that you might earn
> The patch is just an example of how to do it,
>
> Sorry for the confusion that I created without the [RFC PATCH 0/1]
>
> The intension was to ask if anyone thinks that packing of IPv6 address should be there ?
> I would say, much pain for little gain
I tend to agree with that assessment.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2010-10-30 11:23 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-10-29 12:22 [RFC PATCH] IPVS: Backup, Adding IPv6 address packing Hans Schillstrom
2010-10-30 6:53 ` Simon Horman
2010-10-30 10:49 ` Hans Schillstrom
2010-10-30 11:23 ` Simon Horman
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.