Microsoft Branch Cache Hash Offload
Problem this snippet solves:
BranchCache is a technology that Microsoft released with Windows 7 and Server 2008 R2 which can have a profound effect on where users actually source their content and the bandwidth consumed in retrieving that data. It’s fairly common in today’s work world to see global enterprises have multiple branch offices with users who regularly access data from a single centralized datacenter. If you take a look at the data that these users are commonly requesting, you’ll quickly realize that there is often a significant amount of data that is repetitive between the branch users. BranchCache is a technology designed to cut down on the unnecessary round trips from the branch office to the datacenter for data. By keeping an accessible copy of the content in the local branch, there will be a significant reduction in bandwidth used, and users will often be able to get the content faster than retrieving it from the distant datacenter.
This iRule will offload the hash calculation from the servers.
How to use this snippet:
Tested with oneconnect and tcp profiles applied, as well as this http profile:
profile http ms-pccrc-http { compress enable compress buffer size 131072 compress http 1.0 disable compress gzip memory level 16k compress gzip window size 64k }
Code :
when HTTP_REQUEST { set client "[IP::remote_addr]:[TCP::remote_port], URI: [HTTP::uri]" set key "[HTTP::host][HTTP::uri]" persist uie $key if { [HTTP::header "Accept-Encoding"] contains "peerdist" } { set will_peerdist 1 log local0. "$client - peerdist requested" set pcc [session lookup uie $key] if { [llength $pcc] != 0 } { set pl [lrange [persist lookup uie $key] 0 2] if { $pl ne [lindex $pcc 0] } { log local0. "$client - cached peerdist hash does not match persistence: $pl != [lindex $pcc 0]" } else { log local0. "$client - responding with previously cached peerdist hash." HTTP::respond 200 content [binary format a* [lindex $pcc 1]] \ "Content-Encoding" "peerdist" \ "X-P2P-PeerDist" "Version=1.0, ContentLength=[lindex $pcc 2]" \ "ETag" [lindex $pcc 3] \ "Content-Type" [lindex $pcc 4] } unset pl } unset pcc } else { set will_peerdist 0 log local0. "$client - peerdist not requested" } } when HTTP_RESPONSE { # Client can do peerdist, but server response is normal if { $will_peerdist && \ [HTTP::status] == 200 && \ ! [HTTP::header exists "Content-Encoding"] || \ [HTTP::header "Content-Encoding"] eq "identity" } { set clen [HTTP::header "Content-Length"] if { $clen > 0 } { log local0. "[IP::remote_addr]:[TCP::remote_port]->$client - collecting content: $clen" set h_len $clen if { $h_len > 65536 } { set h_len 65536 } HTTP::collect $h_len } else { log local0. "[IP::remote_addr]:[TCP::remote_port]->$client - no content found: $clen, headers: [HTTP::header names]" } } } when HTTP_RESPONSE_DATA { if { ! [info exists offset] } { set offset 0 set blkcnt 0 set blkhashes {} set blkpci {} set segoff 0 set segcnt 0 set seglen 0 set segpci {} set secret [virtual name] HTTP::header replace "Content-Encoding" "peerdist" HTTP::header insert "X-P2P-PeerDist" "Version=1.0, ContentLength=$clen" log local0. "$client - peerdist hashing started" } while { $offset < $clen } { #log local0. "$client - currently collected: [HTTP::payload length], hashing offset: $offset (of $clen)" set h_len [expr {$clen - $offset}] if { $h_len > 65536 } { set h_len 65536 } # if have more to do, but we haven't collected it yet if { [HTTP::payload length] < $h_len } { HTTP::collect $h_len #log local0. "$client - waiting for [expr {$h_len-[HTTP::payload length]}] more, have: [HTTP::payload length]" return } # Hash the current block set blkhashes [binary format a*a* $blkhashes [sha256 [HTTP::payload $h_len]]] # Delete the payload we just hashed since we don't need it anymore HTTP::payload replace 0 $h_len {} incr offset $h_len incr blkcnt # At the Segment boundary if { $blkcnt >= 512 } { # Add a segment hash of block hashes set seglen [expr {$offset - $segoff}] set seghash [sha256 $blkhashes] set seghods [sha256 [binary format a*a* $seghash $secret]] lappend segpci [binary format wiia*a* $segoff $seglen 65536 $seghash $seghods] # Add a block hash lappend blkpci [binary format ia* $blkcnt $blkhashes] set blkhashes {} set blkcnt 0 set segoff $offset incr segcnt log local0. "$client - segment, len: $seglen, cnt: $segcnt, off: $segoff" } } # Didn't end on a block/segment boundary if { $blkcnt > 0 } { # Add a segment hash of block hashes for the last segment set seglen [expr {$offset - $segoff}] set seghash [sha256 $blkhashes] set seghods [sha256 [binary format a*a* $seghash $secret]] lappend segpci [binary format wiia*a* $segoff $seglen 65536 $seghash $seghods] # Add a block hash lappend blkpci [binary format ia* $blkcnt $blkhashes] set blkcnt 0 incr segcnt log local0. "$client - last segment, cnt: $segcnt, len: $seglen" } # Now build the new payload with the hashes set pci [binary format siiii 0x0100 0x800C 0 0 $segcnt] HTTP::payload replace 0 0 $pci set offset [string length $pci] foreach pci $segpci { HTTP::payload replace $offset 0 $pci incr offset [string length $pci] } foreach pci $blkpci { HTTP::payload replace $offset 0 $pci incr offset [string length $pci] } session add uie $key [list [LB::server] [HTTP::payload] $clen [HTTP::header ETag] [HTTP::header Content-Type]] HTTP::release log local0. "$client - content hash completed!" unset -nocomplain pci offset blkcnt blkpci blkhashes secret key unset -nocomplain segoff segcnt seglen segpci seghash seghods }
- Walter_KacynskiCirrostratus
What is the use case that this was applied for? Does it support HTTPS based applications?