<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.geekhold.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" gd:etag="W/&quot;CUcNRns6fyp7ImA9WhRaEUw.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401</id><updated>2012-02-12T22:04:57.517-08:00</updated><category term="mobile" /><category term="GPL" /><category term="Python" /><category term="C Programming" /><category term="embedded" /><category term="bestof" /><category term="blogroll" /><category term="astrostuff" /><category term="Joke" /><category term="ELF" /><category term="filesystem" /><category term="CPU" /><category term="Product Development" /><category term="websites" /><category term="Javascript" /><category term="Ethernet" /><category term="AppEngine" /><category term="Administrivia" /><category term="Engineering Life" /><category term="Virtual Machines" /><category term="control plane" /><category term="social" /><category term="architecture" /><title>Coding Relic</title><subtitle type="html">Random musings on software in an embedded world.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://codingrelic.geekhold.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Denton Gentry</name><uri>https://profiles.google.com/103797409565331693058</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-tdZM5hM_1D0/AAAAAAAAAAI/AAAAAAAAClE/SIaTjGU1fTQ/s512-c/photo.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>268</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.geekhold.com/CodingRelic" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="codingrelic" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">CodingRelic</feedburner:emailServiceId><feedburner:feedburnerHostname xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://feedburner.google.com</feedburner:feedburnerHostname><entry gd:etag="W/&quot;CUcNRns5cSp7ImA9WhRaEUw.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-5944182971495167441</id><published>2012-02-09T06:32:00.000-08:00</published><updated>2012-02-12T22:04:57.529-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-12T22:04:57.529-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="embedded" /><category scheme="http://www.blogger.com/atom/ns#" term="Python" /><title>ATA Commands in Python</title><content type="html">&lt;p itemprop='description'&gt;In software development sometimes you spend time on an implementation which you are unreasonably proud of, but ultimately decide not to use in the product. This is one such story.&lt;/p&gt;

&lt;p&gt;I needed to retrieve information from an attached disk, such as its model and serial number. There are commands which can do this, like hdparm, &lt;a href="http://sg.danny.cz/sg/sdparm.html"&gt;sdparm&lt;/a&gt;, and &lt;a href="http://smartmontools.sourceforge.net/"&gt;smartctl&lt;/a&gt;, but initially I tried to avoid building in a dependency on any such tools by interrogating it from the hard drive directly. In pure Python.&lt;/p&gt;

&lt;p&gt;Snicker all you want, it did work. My first implementation used an older Linux API to retrieve this information, the HDIO_GET_IDENTITY ioctl. This ioctl maps more or less directly to an ATA IDENTIFY or SCSI INQUIRY from the drive. The implementation uses the &lt;a href="http://docs.python.org/library/struct.html"&gt;Python struct module&lt;/a&gt; to define the data structure sent along with the ioctl.&lt;/p&gt;

&lt;pre style="font-family: monospace; font-size: medium; line-height: 1.3em; margin-left: 1em;"&gt;
def GetDriveId(dev):
  """Return information from interrogating the drive.

  This routine issues a HDIO_GET_IDENTITY ioctl to a block device,
  which only root can do.

  Args:
    dev: name of the device, such as 'sda' or '/dev/sda'

  Returns:
    (serial_number, fw_version, model) as strings
  """
  # from /usr/include/linux/hdreg.h, struct hd_driveid
  # 10H = misc stuff, mostly deprecated
  # 20s = serial_no
  # 3H  = misc stuff
  # 8s  = fw_rev
  # 40s = model
  # ... plus a bunch more stuff we don't care about.
  struct_hd_driveid = '@ 10H 20s 3H 8s 40s'
  HDIO_GET_IDENTITY = 0x030d
  if dev[0] != '/':
    dev = '/dev/' + dev
  with open(dev, 'r') as fd:
    buf = fcntl.ioctl(fd, HDIO_GET_IDENTITY, ' ' * 512)
    fields = struct.unpack_from(struct_hd_driveid, buf)
    serial_no = fields[10].strip()
    fw_rev = fields[14].strip()
    model = fields[15].strip()
    return (serial_no, fw_rev, model)
&lt;/pre&gt;


&lt;br/&gt;
&lt;p&gt;No no wait, stop snickering, it does work! It has to run as root, which is one reason why I eventually abandoned this approach.&lt;/p&gt;

&lt;pre style="font-family: monospace; font-size: medium; line-height: 1.3em; margin-left: 1em;"&gt;
$ sudo python hdio.py
('5RY0N6BD', '3.ADA', 'ST3250310AS')
&lt;/pre&gt;


&lt;br/&gt;
&lt;p&gt;HDIO_GET_IDENTITY is deprecated in Linux 2.6, and logs a message saying that sg_io should be used instead. sg_io is an API to send SCSI commands to a device. sg_io also didn't require my entire Python process to run as root, I'd &amp;quot;only&amp;quot; have to give it CAP_SYS_RAWIO. So of course I changed the implementation... still in Python. Stop snickering.&lt;/p&gt;


&lt;br/&gt;
&lt;pre style="font-family: monospace; font-size: medium; line-height: 1.3em; margin-left: 1em;"&gt;
class AtaCmd(ctypes.Structure):
  """ATA Command Pass-Through
     http://www.t10.org/ftp/t10/document.04/04-262r8.pdf"""

  _fields_ = [
      ('opcode', ctypes.c_ubyte),
      ('protocol', ctypes.c_ubyte),
      ('flags', ctypes.c_ubyte),
      ('features', ctypes.c_ubyte),
      ('sector_count', ctypes.c_ubyte),
      ('lba_low', ctypes.c_ubyte),
      ('lba_mid', ctypes.c_ubyte),
      ('lba_high', ctypes.c_ubyte),
      ('device', ctypes.c_ubyte),
      ('command', ctypes.c_ubyte),
      ('reserved', ctypes.c_ubyte),
      ('control', ctypes.c_ubyte) ]


class SgioHdr(ctypes.Structure):
  """&amp;lt;scsi/sg.h&amp;gt; sg_io_hdr_t."""

  _fields_ = [
      ('interface_id', ctypes.c_int),
      ('dxfer_direction', ctypes.c_int),
      ('cmd_len', ctypes.c_ubyte),
      ('mx_sb_len', ctypes.c_ubyte),
      ('iovec_count', ctypes.c_ushort),
      ('dxfer_len', ctypes.c_uint),
      ('dxferp', ctypes.c_void_p),
      ('cmdp', ctypes.c_void_p),
      ('sbp', ctypes.c_void_p),
      ('timeout', ctypes.c_uint),
      ('flags', ctypes.c_uint),
      ('pack_id', ctypes.c_int),
      ('usr_ptr', ctypes.c_void_p),
      ('status', ctypes.c_ubyte),
      ('masked_status', ctypes.c_ubyte),
      ('msg_status', ctypes.c_ubyte),
      ('sb_len_wr', ctypes.c_ubyte),
      ('host_status', ctypes.c_ushort),
      ('driver_status', ctypes.c_ushort),
      ('resid', ctypes.c_int),
      ('duration', ctypes.c_uint),
      ('info', ctypes.c_uint)]

def SwapString(str):
  """Swap 16 bit words within a string.

  String data from an ATA IDENTIFY appears byteswapped, even on little-endian
  achitectures. I don't know why. Other disk utilities I've looked at also
  byte-swap strings, and contain comments that this needs to be done on all
  platforms not just big-endian ones. So... yeah.
  """
  s = []
  for x in range(0, len(str) - 1, 2):
    s.append(str[x+1])
    s.append(str[x])
  return ''.join(s).strip()

def GetDriveIdSgIo(dev):
  """Return information from interrogating the drive.

  This routine issues a SG_IO ioctl to a block device, which
  requires either root privileges or the CAP_SYS_RAWIO capability.

  Args:
    dev: name of the device, such as 'sda' or '/dev/sda'

  Returns:
    (serial_number, fw_version, model) as strings
  """

  if dev[0] != '/':
    dev = '/dev/' + dev
  ata_cmd = AtaCmd(opcode=0xa1,  # ATA PASS-THROUGH (12)
                   protocol=4&amp;lt;&amp;lt;1,  # PIO Data-In
                   # flags field
                   # OFF_LINE = 0 (0 seconds offline)
                   # CK_COND = 1 (copy sense data in response)
                   # T_DIR = 1 (transfer from the ATA device)
                   # BYT_BLOK = 1 (length is in blocks, not bytes)
                   # T_LENGTH = 2 (transfer length in the SECTOR_COUNT field)
                   flags=0x2e,
                   features=0, sector_count=0,
                   lba_low=0, lba_mid=0, lba_high=0,
                   device=0,
                   command=0xec,  # IDENTIFY
                   reserved=0, control=0)
  ASCII_S = 83
  SG_DXFER_FROM_DEV = -3
  sense = ctypes.c_buffer(64)
  identify = ctypes.c_buffer(512)
  sgio = SgioHdr(interface_id=ASCII_S, dxfer_direction=SG_DXFER_FROM_DEV,
                 cmd_len=ctypes.sizeof(ata_cmd),
                 mx_sb_len=ctypes.sizeof(sense), iovec_count=0,
                 dxfer_len=ctypes.sizeof(identify),
                 dxferp=ctypes.cast(identify, ctypes.c_void_p),
                 cmdp=ctypes.addressof(ata_cmd),
                 sbp=ctypes.cast(sense, ctypes.c_void_p), timeout=3000,
                 flags=0, pack_id=0, usr_ptr=None, status=0, masked_status=0,
                 msg_status=0, sb_len_wr=0, host_status=0, driver_status=0,
                 resid=0, duration=0, info=0)
  SG_IO = 0x2285  # &amp;lt;scsi/sg.h&amp;gt;
  with open(dev, 'r') as fd:
    if fcntl.ioctl(fd, SG_IO, ctypes.addressof(sgio)) != 0:
      print "fcntl failed"
      return None
    if ord(sense[0]) != 0x72 or ord(sense[8]) != 0x9 or ord(sense[9]) != 0xc:
      return None
    # IDENTIFY format as defined on pg 91 of
    # http://t13.org/Documents/UploadedDocuments/docs2006/D1699r3f-ATA8-ACS.pdf
    serial_no = SwapString(identify[20:40])
    fw_rev = SwapString(identify[46:53])
    model = SwapString(identify[54:93])
    return (serial_no, fw_rev, model)
&lt;/pre&gt;


&lt;br/&gt;
&lt;p&gt;For the unbelievers out there, this one works too.&lt;/p&gt;

&lt;pre style="font-family: monospace; font-size: medium; line-height: 1.3em; margin-left: 1em;"&gt;
$ sudo python sgio.py
('5RY0N6BD', '3.ADA', 'ST3250310AS')
&lt;/pre&gt;


&lt;br/&gt;
&lt;p&gt;So, there you go. HDIO_GET_IDENTITY and SG_IO implemented in pure Python. They do work, but in the process of working on this and reading existing code it became clear that low level ATA handling is fraught with peril. The disk industry has been iterating this interface for decades, and there is a &lt;b&gt;ton&lt;/b&gt; of gear out there that made questionable choices in how to interpret the spec. Most of the code in existing utilities is not to implement the base operations but instead to handle the quirks from various manufacturers. I decided that I didn't want to go down that path, and will instead rely on forking &lt;a href="http://sg.danny.cz/sg/sdparm.html"&gt;sdparm&lt;/a&gt; and &lt;a href="http://smartmontools.sourceforge.net/"&gt;smartctl&lt;/a&gt; as needed.&lt;/p&gt;

&lt;p&gt;I'll just leave this post here for search engines to find. I'm sure there is a ton of demand for this information.&lt;/p&gt;

&lt;p&gt;Stop snickering.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-5944182971495167441?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=Gmh2YNf8OQw:gTAgGKmP7cA:Osvv7CGXBvU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=Osvv7CGXBvU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=Gmh2YNf8OQw:gTAgGKmP7cA:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/Gmh2YNf8OQw" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/5944182971495167441?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/5944182971495167441?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2012/02/ata-commands-in-python.html" title="ATA Commands in Python" /><author><name>Denton Gentry</name><uri>https://profiles.google.com/103797409565331693058</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-tdZM5hM_1D0/AAAAAAAAAAI/AAAAAAAAClE/SIaTjGU1fTQ/s512-c/photo.jpg" /></author></entry><entry gd:etag="W/&quot;D08BQX0zfip7ImA9WhRbF08.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-107861682633694022</id><published>2012-02-02T07:01:00.001-08:00</published><updated>2012-02-08T10:30:50.386-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-02-08T10:30:50.386-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="embedded" /><title>ISC DHCP VIVO config</title><content type="html">&lt;p&gt;In addition to its role in assigning IPv4 addresses, DHCP has an options mechanism to send other bits of data between client and server. For example there are options to provide the DNS and NTP server addresses along with the client's assigned IP address. In its request, the client lists the options it would like to receive. The server fills in whichever ones it can.&lt;/p&gt;

&lt;p&gt;DHCP has always allowed for vendor extensions of the available options, &lt;a href="http://www.ietf.org/rfc/rfc1497.txt"&gt;inheriting this support&lt;/a&gt; from the earlier BOOTP protocol. The original vendor extension mechanism was very simple: use option 43, and put whatever you like there. A mechanism was provided to encode multiple sub-options within the option 43 data, but made no attempt to coordinate between different vendors use of the space. Vendors immediately began creating conflicts, using the same numeric codes for different means simultaneously. This led to a variety of heroic hacks in which the client would populate its request with magic values which the server would use to figure out the set of vendor options to supply.&lt;/p&gt;

&lt;p&gt;DHCP6 defined a more complex encoding, where each vendor includes their unique &lt;a href="http://www.iana.org/assignments/enterprise-numbers"&gt;IANA Enterprise Number&lt;/a&gt; as part of its option. Options from different vendors can be accommodated simultaneously. This &lt;a href="http://www.ietf.org/rfc/rfc3925.txt"&gt;Vendor-Identifying Vendor Options (VIVO)&lt;/a&gt; encoding was also added back to DHCP4 as options 124 and 125. DHCP4 thus has two separate vendor option mechanisms in common use.&lt;/p&gt;


&lt;br/&gt;
&lt;h3&gt;ISC DHCPd&lt;/h3&gt;
&lt;p&gt;The &lt;a href="http://www.isc.org/software/dhcp"&gt;ISC DHCP server&lt;/a&gt; can support VIVO options using several different mechanisms. The first, and so far as I can tell most common, is to specify the byte-level payload. The administrator pores over RFCs and vendor documentation to come up with the magic string of bytes to send and types it into dhcpd.conf, where it immediately becomes magic voodoo that everyone is afraid to touch for fear of breaking something.&lt;/p&gt;

&lt;p&gt;Avoiding magic byte strings by specifying the format of the options is more difficult to get working, but easier to maintain and understand. We'll consider an example here.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vendor: Frobozzco&lt;/li&gt;
&lt;li&gt;IANA Enterprise Number (IEN): 12345&lt;/li&gt;
&lt;li&gt;Code #1: a text string containing the location within the maze.&lt;/li&gt;
&lt;li&gt;Code #2: an integer describing the percentage likelihood of being eaten by a grue.&lt;br/&gt;&lt;i&gt;In practice this is always 100%, which many clients simply hard-code.&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;br/&gt;
&lt;p&gt;To implement this in the DHCP config, we define an option space for frobozzco. This just creates a namespace; we bind that namespace to the numeric IEN later. We have to tell DHCP how wide to make the code and length fields. DHCP4 usually uses 1 byte fields, while DHCP6 generally uses 2 bytes. Most of the time vendors don't specify the width they use, and if so you should assume the normal sizes for the protocol. The example below comes from a DHCP6 config, so the code and length are both declared as two bytes. After we've declared all of the option codes, we bind the frobozzco option space to its numeric IANA Enterprise Number. Use of IEN for DHCP is called the Vendor Specific Information Option, so the syntax in the DHCP configuration labels this vsio.{option space name}&lt;/p&gt;

&lt;pre style="font-family: monospace; font-size: medium; line-height: 1.3em; margin-left: 3em;"&gt;
option space frobozzco code width 2 length width 2;
option frobozzco.maze-location code 1 = text;
option frobozzco.grue-probability code 2 = uint8;
option vsio.frobozzco code 12345 = encapsulate frobozzco;
&lt;/pre&gt;


&lt;br/&gt;
&lt;p&gt;Owing to the long and sordid history of numbering conflicts, most vendor extensions define a  &lt;i&gt;secret handshake.&lt;/i&gt; The client inserts a specific value into a field in its request to trigger the server to respond with the options for that vendor. Frobozzco has decreed that clients should send the string &amp;quot;look north&amp;quot; as a vendor-class option in the request. A DHCP6 vendor-class consists of the vendor's IEN followed by the content. In our case the content consists of another two byte length field, followed by the string. ISC DHCP 4.x doesn't define a type for handling vendor-class in the config but we can construct one using a record, which is a collection of fields defined inside brackets.&lt;/p&gt;

&lt;pre style="font-family: monospace; font-size: medium; line-height: 1.3em; margin-left: 3em;"&gt;
option dhcp6.vendor-class code 16 = {integer 32, integer 16, string};

# length=14 bytes, Frobozzco IEN, content=look north
send dhcp6.vendor-class 12345 14 "look north";
&lt;/pre&gt;


&lt;br/&gt;
&lt;p&gt;Finally, we have to provide a script for dhclient to run to handle the received options. We'll get to the client script a bit later, for now just assume it is in /usr/local/sbin/dhclient-script. Putting it all together, the dhclient6.conf should look like this.&lt;/p&gt;

&lt;pre style="font-family: monospace; font-size: medium; line-height: 1.3em; margin-left: 3em;"&gt;
script "/usr/local/sbin/dhclient-script";

option space frobozzco code width 2 length width 2;
option frobozzco.maze-location code 1 = text;
option frobozzco.grue-probability code 2 = uint8;
option vsio.frobozzco code 12345 = encapsulate frobozzco;

option dhcp6.vendor-class code 16 = {integer 32, integer 16, string};

interface "eth0" {
    also request dhcp6.vendor-opts;
    send dhcp6.vendor-class 12345 10 "look north";
}
&lt;/pre&gt;


&lt;br/&gt;
&lt;h3&gt;dhclient-script&lt;/h3&gt;
&lt;p&gt;On the client we also must provide the script for dhclient to run. The OS vendor will have provided one, often in /sbin or /usr/sbin. We'll copy it, and add handling.&lt;/p&gt;

&lt;p&gt;dhclient passes in environment variables for each DHCP option. The name of the variable is &amp;quot;new_&amp;lt;option space name&amp;gt;_&amp;lt;option name&amp;gt;&amp;quot; For the example config above, we'd define a shell script function to write our two options to files in /tmp.&lt;/p&gt;

&lt;pre style="font-family: monospace; font-size: medium; line-height: 1.3em; margin-left: 3em;"&gt;
make_frobozzco_files() {                                                       
  mkdir /tmp/frobozzco                                            
  if [ "x${new_frobozzco_maze_location}" != x ] ; then         
    echo ${new_frobozzco_maze_location} &gt; /tmp/frobozzco/maze_location                 
  fi                                                                      
  if [ "x${new_frobozzco_grue_probability}" != x ] ; then
    echo ${new_frobozzco_grue_probability} &gt; /tmp/frobozzco/grue_probability
  fi                                                             
}
&lt;/pre&gt;

&lt;p&gt;The dhclient-script provided with the OS will have handling for DNS nameservers. Adding a call to make_frobozzco_files at the same points in the script which handle /etc/resolv.conf is a reasonable approach to take.&lt;/p&gt;

&lt;p&gt;I'm mostly blogging this for my own future use, to be able to find how to do something I remember doing before. There you go, future me.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-107861682633694022?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=lWK3vgri4mc:fXTamvOMo5U:Osvv7CGXBvU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=Osvv7CGXBvU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=lWK3vgri4mc:fXTamvOMo5U:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/lWK3vgri4mc" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/107861682633694022?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/107861682633694022?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2012/02/isc-dhcp-vivo-config.html" title="ISC DHCP VIVO config" /><author><name>Denton Gentry</name><uri>https://profiles.google.com/103797409565331693058</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-tdZM5hM_1D0/AAAAAAAAAAI/AAAAAAAAClE/SIaTjGU1fTQ/s512-c/photo.jpg" /></author></entry><entry gd:etag="W/&quot;CEYFSXg4eyp7ImA9WhRbEE8.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-6530957116169868452</id><published>2012-01-31T06:01:00.000-08:00</published><updated>2012-01-31T07:01:58.633-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-31T07:01:58.633-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="filesystem" /><category scheme="http://www.blogger.com/atom/ns#" term="embedded" /><title>certdata.txt</title><content type="html">&lt;p&gt;When building the software for a new device there are a ton of things which need to go into the filesystem: binaries, libraries, device nodes, a bunch of configuration files, etc. One of the chunks of essential data is a list of trusted certificate authorities for libssl, commonly stored in /etc/ssl/ca_certificates.crt. Its common practice to grab a &lt;a href="http://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt"&gt;list of certificates from mozilla.org,&lt;/a&gt; and there are various Perl and Python scripts floating around in the search engines to assemble this list into a PEM file suitable for libssl.&lt;/p&gt;

&lt;p&gt;2011 was not a good year for certificate authorities. &lt;a href="http://en.wikipedia.org/wiki/DigiNotar"&gt;DigiNotar was seized&lt;/a&gt; by the Dutch government after it became clear they had been thoroughly breached and generated fraudulent certificates for many large domains. Several Comodo resellers &lt;a href="http://blogs.comodo.com/it-security/data-security/the-recent-ra-compromise/"&gt;were similarly compromised&lt;/a&gt; and generated bogus certs for some of the same sites. Browser makers responded by encoding a list of toxic certificates into the browser, to reject any certificate signed by them.&lt;/p&gt;

&lt;p&gt;&lt;i&gt;Encoding a list of toxic certificates&lt;/i&gt; is the key phrase in that paragraph. As of 2011, Mozilla's certdata.txt contains both trusted CAs and absolutely untrustworthy, revoked CAs. There is metadata in the entry describing how it should be treated, but several of the scripts floating around grab &lt;i&gt;everything&lt;/i&gt; listed in certdata.txt and &lt;b&gt;put it in the PEM file.&lt;/b&gt; This is disastrous.&lt;/p&gt;

&lt;p&gt;The code to search for is CKT_NSS_NOT_TRUSTED. The utility you are using should check for that type, and skip it. If there is no handling for CKT_NSS_NOT_TRUSTED, then the utility you are using is absolutely broken. Don't use it. I know of at least two which handle this correctly:&lt;/p&gt;

&lt;ul&gt;
 &lt;li&gt;Adam Langley's &lt;a href="https://github.com/agl/extract-nss-root-certs"&gt;extract-nss-root-certs&lt;/a&gt;, written in Go. &lt;a href="http://www.imperialviolet.org/2012/01/30/mozillaroots.html"&gt;Read his announcement for more information&lt;/a&gt;.&lt;/li&gt;
 &lt;li&gt;OpenSUSE's &lt;a href="http://gitorious.org/opensuse/ca-certificates/blobs/master/extractcerts.pl"&gt;extractcerts.pl&lt;/a&gt;, written in Perl&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-6530957116169868452?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=AqBRQEY9gZs:2kS7rPIXvA4:Osvv7CGXBvU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=Osvv7CGXBvU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=AqBRQEY9gZs:2kS7rPIXvA4:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/AqBRQEY9gZs" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/6530957116169868452?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/6530957116169868452?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2012/01/certdatatxt.html" title="certdata.txt" /><author><name>Denton Gentry</name><uri>https://profiles.google.com/103797409565331693058</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-tdZM5hM_1D0/AAAAAAAAAAI/AAAAAAAAClE/SIaTjGU1fTQ/s512-c/photo.jpg" /></author></entry><entry gd:etag="W/&quot;CkACQn0yfip7ImA9WhRVGEQ.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-2837678425237204764</id><published>2012-01-18T04:46:00.000-08:00</published><updated>2012-01-18T04:46:03.396-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-18T04:46:03.396-08:00</app:edited><title>Offense</title><content type="html">&lt;p&gt;SOPA isn't dead. It hasn't been defeated. It hasn't been stopped. Its just regrouping.&lt;/p&gt;

&lt;p&gt;Their main mistake was in allowing it to become publicly known too long before a decisive vote. Its backers will try again, next time ramming it through in the dead of night. They'll give it a scary title, as anything can be justified if the title of the bill is scary enough.&lt;/p&gt;

&lt;p&gt;Bills like SOPA are an attempt to legislate a return to media economics the way it used to be, where the sheer cost of distributing content formed a high barrier to entry. Its the economics of scarcity. Better yet, the law would require &lt;i&gt;someone else&lt;/i&gt; to pay the cost of creating this scarcity. If the cost of any infringement, intentional or not, third party or first party, can be made so overwhelming as to be ruinous (and incidentally decoupled from any notion of the actual damage from the infringement), then cheap distribution via the Internet can be made expensive again. We can get back to the cozy media business of prior decades.&lt;/p&gt;

&lt;p&gt;Its time to stop playing defense, desperately trying to stop each of these bills.&lt;/p&gt;

&lt;p&gt;Its time to start playing offense.&lt;/p&gt;


&lt;br/&gt;
&lt;p&gt;The workings of government are obscure and impenetrable. There are reams of data produced in the form of minutes, committee reports, the &lt;i&gt;Federal Register,&lt;/i&gt; and other minutiae, but the whole remains an opaque mass. Lobbyists and political operatives thrive in this environment, as they understand more about the mechanisms by which it operates. Yet one of the recent core competencies of the technology industry is Big Data. There are conclusions which can be drawn from trends within the dataset without having to semantically understand all of it.&lt;/p&gt;

&lt;p&gt;I have to believe there are things the tech industry can do beyond simply increasing lobbying budgets.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-2837678425237204764?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=gJIcjgdpdCk:MP8jJcDBEYc:Osvv7CGXBvU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=Osvv7CGXBvU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=gJIcjgdpdCk:MP8jJcDBEYc:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/gJIcjgdpdCk" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/2837678425237204764?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/2837678425237204764?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2012/01/offense.html" title="Offense" /><author><name>Denton Gentry</name><uri>https://profiles.google.com/103797409565331693058</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-tdZM5hM_1D0/AAAAAAAAAAI/AAAAAAAAClE/SIaTjGU1fTQ/s512-c/photo.jpg" /></author></entry><entry gd:etag="W/&quot;DE8BRXw-fyp7ImA9WhRVFEs.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-7715799930034397510</id><published>2012-01-13T07:00:00.000-08:00</published><updated>2012-01-13T07:00:54.257-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-13T07:00:54.257-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Ethernet" /><category scheme="http://www.blogger.com/atom/ns#" term="Product Development" /><title>Merchant Silicon</title><content type="html">&lt;p&gt;Last week &lt;a href="https://twitter.com/#!/etherealmind"&gt;Greg Ferro&lt;/a&gt; wrote about &lt;a href="http://etherealmind.com/merchant-silicon-vendor-software-rise-lost-opportunity/"&gt;the use of merchant silicon&lt;/a&gt; in networking products. I'd like to share some thoughts on the topic.&lt;/p&gt;


&lt;br/&gt;
&lt;h3&gt;Chip cost&lt;/h3&gt;
&lt;p&gt;&lt;img border="0" width="71" height="78" src="http://2.bp.blogspot.com/-ycpdAkMhU0w/TxBBDhPRQSI/AAAAAAAAFO8/5mm6BamfqHo/s160/dollars.png" align="right" style="border: 1px #777; margin: 0 0 1em 1em;" alt="Fistful of dollars" title="Those should probably be $10 bills, with inflation and all"&gt;We know the story by now: by selling chips into products from multiple networking companies, commodity chips sell in large volume and benefit from larger discounts. This is a compelling factor in the low end of the switching market, where margins are thin and a primary selling point is price.&lt;/p&gt;

&lt;p&gt;Yet low price of the switch silicon is not a decisive factor in the midrange and high end of the switching market, where products are more featureful and sell at higher prices. The price of those products is not based on the cost of materials, its based on what the market will bear. The market has traditionally borne a lot: Cisco's profit margins in these segments have been legendary for a decade.&lt;/p&gt;

&lt;p&gt;In my experience, chip price was not a decisive factor in the wholesale move to merchant silicon.&lt;/p&gt;


&lt;br/&gt;
&lt;h3&gt;Non Recurring Engineering (NRE cost)&lt;/h3&gt;
&lt;p&gt;&lt;img border="0" width="73" height="66" src="http://2.bp.blogspot.com/-w2_ET2NAhEo/TxBBOkF3maI/AAAAAAAAFPI/-X_um4ki6GE/s160/ASIC.jpg" align="right" style="border: 1px #777; margin: 0 0 1em 1em;" alt="Silicon chip" title="That is not actually a switch chip. Shhhh. Do not tell anyone, please."&gt;Say it costs $10 million to design a chipset for a high end switch, and the resulting set of silicon costs $500 in the expected volumes. If that high end switch sells 10,000 units in its first year then the NRE cost for developing it amounts to $1,000 per unit, double the cost of buying the chip itself. The longer the model remains in production the more its cost can be amortized... but the company has to pay the complete cost to develop the silicon before the first unit is sold.&lt;/p&gt;

&lt;p&gt;In the midrange and high end switch markets, the strongest pitch made by merchant semiconductor suppliers wasn't the per-chip cost. A stronger pitch for those segments was elimination of NRE. The networking company didn't have to bear the cost of chip development up front. The company &lt;b&gt;did&lt;/b&gt; pay the cost of development, but it would be factored into the unit price and pay-as-you-go rather than upfront.&lt;/p&gt;

&lt;p&gt;Yet even NRE savings wasn't usually enough to convince a networking company to give up its own ASIC designs. Most  realized that to do so was to give up a substantial portion of their ability to differentiate their products. Several vendors adopted a hybrid approach. They used merchant silicon to provide the fabric and handle simple cases of packet forwarding, and configured flow rules to steer interesting packets out to a separate device for additional handling. Costs were reduced by only having to design that specialized chip for a subset of the total traffic through the box, but they retained an ability to differentiate features.&lt;/p&gt;

&lt;p&gt;In my experience, eliminating the burden of NRE was not a decisive factor in the move to merchant silicon.&lt;/p&gt;


&lt;br/&gt;
&lt;h3&gt;Schedule&lt;/h3&gt;
&lt;p&gt;&lt;img border="0" width="141" height="100" src="http://2.bp.blogspot.com/-dqJw7-Ij-qQ/TxBBXvBgdWI/AAAAAAAAFPU/o622MMrNk74/s160/gantt.png" align="right" style="border: 1px #777; margin: 0 0 1em 1em;" alt="Gantt chart" title="That is from my real day-job project. No fooling."&gt;The merchant silicon vendors of the world can dedicate more ASIC engineers to their projects. This isn't as big a win as it sounds: tripling the size of the design team does &lt;u&gt;not&lt;/u&gt; result in a chip with 3x the features or in 1/3rd the time. As with software projects (see &lt;i&gt;The Mythical Man Month),&lt;/i&gt; the increasing coordination overhead of a larger team results in steeply diminishing returns.&lt;/p&gt;

&lt;p&gt;Instead, merchant silicon vendors have the luxury of working on multiple projects in parallel. They can have two teams leapfrogging each other, each working on a multiyear timeline and introducing their products in interleaving years. Alternately, they can target different chips at different market segments. They rely on their SDK to hide gratuitous differences which they happened to introduce, and only make their customers deal with the truly differentiating features of the different chips.&lt;/p&gt;

&lt;p&gt;It is difficult to make a case to spend two years to develop custom silicon for a product when merchant silicon with sufficient features is expected to be available a year earlier. Merchant silicon suppliers share details of their roadmap very early, even before the feature set is finalized. This lets them incorporate feedback into the features for the final product, but they also do it to derail in-house silicon efforts.&lt;/p&gt;

&lt;p&gt;Yet in my experience at least, though schedule is a decisive factor, this isn't the full story.&lt;/p&gt;


&lt;br/&gt;
&lt;h3&gt;Misaligned Incentives&lt;/h3&gt;
&lt;p&gt;When leading a chip development effort, the biggest fear is not that the chip will have bugs. Many ASIC bugs can be worked around in software.&lt;/p&gt;

&lt;p&gt;The biggest fear is not that the chip will be larger and more costly than planned. That is a negotiation issue with the silicon fab, or a business issue in positioning the product.&lt;/p&gt;

&lt;p&gt;The biggest fear is that the chip will be &lt;b&gt;late.&lt;/b&gt; Missing the market window is the worst kind of failure for an ASIC. The design team produces a chip which meets all requirements, but comes at a time when the market no longer cares. The tardy product will face significant pricing pressure on the day of introduction, more so the longer competitive products have been available.&lt;/p&gt;

&lt;p&gt;The technical leadership of an internal ASIC project is therefore incented to plan a schedule which they are sure they can meet. They'll use realistic timelines for the different phases of the product, and include sufficient padding to handle unexpected problems. They will produce best case timelines as well, but those tend to be discounted by the project leadership as unrealistic.&lt;/p&gt;

&lt;p&gt;The technical leadership inside merchant semiconductor companies face the same issues, and produce the same sort of schedule which they are confident they can meet. The difference is, that conservative schedule is not handed out to the decision makers at the customer networking vendors. A more optimistic schedule is maintained and presented to customers - not rosy best case, but certainly optimistic. Everybody knows that schedule will slip, even the customers themselves... but nonetheless it works. Customers work from the optimistic schedule because that is all they have. It increases the difference in schedule between in-house and merchant options by several quarters.&lt;/p&gt;


&lt;br/&gt;
&lt;h3&gt;The Point of No Return&lt;/h3&gt;
&lt;p&gt;ASIC design requires some rather specialized skill sets. There is a great deal of similarity between chip design and software design, but not so much that one can switch freely back and forth. If there is not an active chip development effort underway, the ASIC team tends to run out of interesting things to work on.&lt;/p&gt;

&lt;p&gt;When a company begins seriously contemplating building their high end products using merchant silicon, even if the management tries to keep it low key, it becomes pretty obvious internally. You have to pull in senior technical folks from the software, hardware, and ASIC teams to help with the evaluation. News spreads. Gossip spreads faster. If the ASIC team becomes convinced that there will be no further chip projects, they start to move on.&lt;/p&gt;

&lt;p&gt;It can easily become a self-fulfilling prophecy: serious consideration of a move to merchant silicon leads to loss of the capability to develop custom ASICs.&lt;/p&gt;


&lt;br/&gt;
&lt;h3&gt;Why it Matters&lt;/h3&gt;
&lt;p&gt;We talk a lot about Software Defined Networking. The term, consciously or not, tends to make people think the networking is all in software and the hardware is insignificant. That isn't actually true, as the SDN can only utilize   actions which the hardware can actually do, but it illustrates how much less we value we put in hardware now.&lt;/p&gt;

&lt;p&gt;In the context of SDN, reducing switch hardware diversity is actually a good thing. It results in a more uniform set of capabilities in networks, and a smaller set of cases for the SDN controller to have to handle. Networking used to be dominated by the hardware designs, but it has moved on now. I think that is a good thing.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-7715799930034397510?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=ttENvPD40ck:lvTxVg1XjP8:Osvv7CGXBvU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=Osvv7CGXBvU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=ttENvPD40ck:lvTxVg1XjP8:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/ttENvPD40ck" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/7715799930034397510?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/7715799930034397510?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2012/01/merchant-silicon.html" title="Merchant Silicon" /><author><name>Denton Gentry</name><uri>https://profiles.google.com/103797409565331693058</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-tdZM5hM_1D0/AAAAAAAAAAI/AAAAAAAAClE/SIaTjGU1fTQ/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-ycpdAkMhU0w/TxBBDhPRQSI/AAAAAAAAFO8/5mm6BamfqHo/s72-c/dollars.png" height="72" width="72" /></entry><entry gd:etag="W/&quot;C08NQXk_fCp7ImA9WhRWEkQ.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-2914997867005696429</id><published>2011-12-30T14:43:00.000-08:00</published><updated>2011-12-30T16:38:10.744-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-30T16:38:10.744-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="social" /><title>#emotivehashtags</title><content type="html">&lt;p&gt;Earlier this week &lt;a href="https://twitter.com/#!/samfbiddle"&gt;Sam Biddle of Gizmodo&lt;/a&gt; published &lt;a href="http://gizmodo.com/5869538/how-the-hashtag-is-ruining-the-english-language"&gt;How the Hashtag Is Ruining the English Language&lt;/a&gt;, decrying the use of hashtags to add additional color or meaning to text. Quoth the article, &amp;quot;The hashtag is a vulgar crutch, a lazy reach for substance in the personal void &amp;ndash; written clipart.&amp;quot; #getoffhislawn&lt;/p&gt;

&lt;p&gt;Written communication has never been as effective as in-person conversation, nor even as simple audio via telephone. Presented with plain text, we lack a huge array of additional channels for meaning: posture, facial expression, tone, cadence, gestures, etc. Smileys can be seen as an early attempt to add emotional context to online communication, albeit a limited one. #deathtosmileys&lt;/p&gt;

&lt;p&gt;Yet language evolves to suit our needs and to fit advances communications technology. A specific example: in the US we commonly say &amp;quot;Hello&amp;quot; as a greeting. Its considered polite, and it has always been the common practice... except that it &lt;i&gt;hasn't.&lt;/i&gt; &lt;a href="http://www.collectorcafe.com/article_archive.asp?article=800&amp;id=1507"&gt;The greeting &lt;i&gt;Hello&lt;/i&gt; entered the English language&lt;/a&gt; in the mid 19th century &lt;a href="http://www.npr.org/templates/story/story.php?storyId=3602515"&gt;with the invention of the telephone.&lt;/a&gt; The custom until that time of speaking only after a proper introduction simply didn't work on the telephone, it wasn't practical over the distances involved to coordinate so many people. Use of &lt;i&gt;Hello&lt;/i&gt; spread from the telephone into all areas of interaction. I suspect there were people at the time who bemoaned and berated the verbal crutch of the "hello" as they watched it push aside the more finely crafted greetings of the time. #getofftheirlawn&lt;/p&gt;

&lt;p&gt;So now we have hashtags. Spawned by the space-constrained medium of the tweet, they are now spreading to other written forms. That they find traction in longer form media is an indication that they fill a need. They supply context, overlay emotional meaning, and convey intent, all lacking in current practice. Its easy to label hashtags as lazy or somehow vulgar. &amp;quot;[W]hy the need for metadata when regular words have been working so well?&amp;quot; questions the Gizmodo piece. Yet the sad reality is that regular words &lt;u&gt;haven't&lt;/u&gt; been working so well. Even in the spoken word there is an enormous difference between oratory and casual conversation. A moving speech, filled with meaning in every phrase, takes a long time to prepare and rehearse. Its a rare event, not the norm day to day. The same holds true in the written word. &amp;quot;I apologize that this letter is so long - I lacked the time to make it short.&amp;quot; quipped &lt;a href="http://en.wikipedia.org/wiki/Blaise_Pascal"&gt;Blaise Pascal&lt;/a&gt; in the 17th century.&lt;/p&gt;


&lt;br/&gt;
&lt;h3&gt;Disambiguation&lt;/h3&gt;
&lt;p&gt;Gizmodo even elicited a response from &lt;a href="http://www.chomsky.info/"&gt;Noam Chomsky,&lt;/a&gt; probably via email, &amp;quot;Don't use Twitter, almost never see it.&amp;quot;&lt;/p&gt;

&lt;p&gt;What I find most interesting about Chomsky's response is that it so perfectly illustrates the problem which emotive hashtags try to solve: his phrasing is slightly ambiguous. It could be interpreted as Chomsky saying he doesn't use Twitter and so never sees hashtags, &lt;b&gt;or&lt;/b&gt; that anyone bothered by hashtags shouldn't use Twitter so they won't see them. He probably means the former, but in an in-person conversation there would be no ambiguity. Facial expression would convey his unfamiliarity with Twitter.&lt;/p&gt;

&lt;p&gt;For Chomsky, adding a hashtag would require extra thought and effort which could instead have gone into rewording the sentence. That, I think, is the key. For those to whom hashtags are extra work, it all seems silly and even stupid. For those whose main form of communication is short texts, it doesn't. #getoffmylawntoo&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-2914997867005696429?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=khF3acclRLs:0ac3V9vSuHM:Osvv7CGXBvU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=Osvv7CGXBvU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=khF3acclRLs:0ac3V9vSuHM:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/khF3acclRLs" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/2914997867005696429?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/2914997867005696429?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2011/12/emotivehashtags.html" title="#emotivehashtags" /><author><name>Denton Gentry</name><uri>https://profiles.google.com/103797409565331693058</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-tdZM5hM_1D0/AAAAAAAAAAI/AAAAAAAAClE/SIaTjGU1fTQ/s512-c/photo.jpg" /></author></entry><entry gd:etag="W/&quot;DUEFRHs7eCp7ImA9WhRXFUs.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-3074810240735372500</id><published>2011-12-22T07:26:00.001-08:00</published><updated>2011-12-22T07:26:55.500-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-22T07:26:55.500-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Joke" /><title>Refactoring Is Everywhere</title><content type="html">&lt;center&gt;&lt;img border="0" width="585" height="418" src="http://4.bp.blogspot.com/-xLnoAkzlps0/TvNL8LmSY8I/AAAAAAAAE0U/GRZUidMcywE/s640/refactoring.jpg" style="margin-top: 1em; border: 0px;" alt="Large Ditch Witch" title="Is the Large Hadron Collider a Proton Refactoring tool, or an actual subatomic IDE?" /&gt;&lt;/center&gt;

&lt;p&gt;The utilities used to run from poles, now they are underground. The functionality is unchanged, but the implementation is cleaner.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-3074810240735372500?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=ADAvsDClzlk:s5tGoNV7mjw:Osvv7CGXBvU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=Osvv7CGXBvU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=ADAvsDClzlk:s5tGoNV7mjw:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/ADAvsDClzlk" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/3074810240735372500?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/3074810240735372500?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2011/12/refactoring-is-everywhere.html" title="Refactoring Is Everywhere" /><author><name>Denton Gentry</name><uri>https://profiles.google.com/103797409565331693058</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-tdZM5hM_1D0/AAAAAAAAAAI/AAAAAAAAClE/SIaTjGU1fTQ/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-xLnoAkzlps0/TvNL8LmSY8I/AAAAAAAAE0U/GRZUidMcywE/s72-c/refactoring.jpg" height="72" width="72" /></entry><entry gd:etag="W/&quot;CUUCQXw9eyp7ImA9WhRXE00.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-3337929988166795368</id><published>2011-12-19T06:01:00.000-08:00</published><updated>2011-12-19T06:01:00.263-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-19T06:01:00.263-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Joke" /><title>Multiple Inheritance</title><content type="html">&lt;center&gt;&lt;img border="0" width="500" height="375" src="http://3.bp.blogspot.com/-sHqn2_66YT4/Tu8oSqvnXmI/AAAAAAAAEyo/9vC0YdqdzuE/s640/hotdogtopi.jpg" style="margin-top: 1em; border: 0px;" alt="Hot Dog cut to resemble octopus tentacles" title="My daughter thought this was funny, but refused to eat it." /&gt;&lt;/center&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-3337929988166795368?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=qrInHqS_j-A:dQkDbl03tVQ:Osvv7CGXBvU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=Osvv7CGXBvU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=qrInHqS_j-A:dQkDbl03tVQ:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/qrInHqS_j-A" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/3337929988166795368?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/3337929988166795368?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2011/12/multiple-inheritance.html" title="Multiple Inheritance" /><author><name>Denton Gentry</name><uri>https://profiles.google.com/103797409565331693058</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-tdZM5hM_1D0/AAAAAAAAAAI/AAAAAAAAClE/SIaTjGU1fTQ/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-sHqn2_66YT4/Tu8oSqvnXmI/AAAAAAAAEyo/9vC0YdqdzuE/s72-c/hotdogtopi.jpg" height="72" width="72" /></entry><entry gd:etag="W/&quot;A0AAR3s5eCp7ImA9WhRXEEk.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-4578599640898994150</id><published>2011-12-16T07:35:00.000-08:00</published><updated>2011-12-16T07:35:46.520-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-16T07:35:46.520-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Engineering Life" /><title>The Ada Initiative 2012</title><content type="html">&lt;p&gt;&lt;a href="http://supportada.org/donate"&gt;&lt;img border="0" width="204" height="137" align="right" src="http://3.bp.blogspot.com/-Oa6mVt1-6jA/TutOu9k2tCI/AAAAAAAAEqM/5yzLl-xEDd8/s320/adadonate.png" style="margin: 0;" alt="Donate to the Ada Initiative"&gt;&lt;/a&gt;Earlier this year I donated seed funding to the &lt;a href="http://adainitiative.org/"&gt;Ada Initiative&lt;/a&gt;, a non-profit organization dedicated to increasing participation of women in open technology and culture. &lt;a href="http://adainitiative.org/2011/12/example-conference-anti-harassment-policy-turns-one-year-old/"&gt;One of their early efforts&lt;/a&gt; was development of an &lt;a href="http://geekfeminism.wikia.com/wiki/Conference_anti-harassment"&gt;example anti-harassment policy&lt;/a&gt; for conference organizers, attempting to counter a number of high profile incidents of sexual harassment at events. Lacking any sort of plan for what to do after such an incident, conference organizers often did not respond effectively. This creates an incredibly hostile environment, and makes it even harder for women in technology to advance their careers through networking. Developing a coherent, written policy is a first step toward solving the problem.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://supportada.org/donate"&gt;The Ada Initiative is now raising funds&lt;/a&gt; for &lt;a href="http://adainitiative.org/2011/11/what-we-plan-to-do-with-your-donations/"&gt;2012 activities, including:&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ada’s Advice: a guide to resources for helping women in open tech/culture&lt;/li&gt;
&lt;li&gt;Ada’s Careers: a career development community for women in open tech/culture&lt;/li&gt;
&lt;li&gt;First Patch Week: help women write and submit a patch in a week&lt;/li&gt;
&lt;li&gt;&lt;a href="http://adainitiative.org/2011/10/ada-initiative-to-hold-first-adacamp-in-melbourne-australia/"&gt;AdaCamp&lt;/a&gt; and AdaCon: (un)conferences for women in open tech/culture&lt;/li&gt;
&lt;li&gt;Women in Open Source Survey: annual survey of women in open source&lt;/li&gt;
&lt;/ul&gt;

&lt;br/&gt;&amp;nbsp;&lt;br/&gt;
&lt;h3&gt;For me personally&lt;/h3&gt;
&lt;p&gt;There are many barriers discouraging women from participating in the technology field. Donating to the Ada Initiative is one thing I'm doing to try to change that. I'm posting this to &lt;a href="http://supportada.org/donate"&gt;ask other people to join me in supporting this effort&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;My daughter is 6. The status quo is unacceptable. Time is short.&lt;/p&gt;
&lt;br/&gt;

&lt;center&gt;&lt;a href="http://supportada.org/donate"&gt;&lt;img border="0" width="480" height="360" src="http://2.bp.blogspot.com/-bxQhlmHrSHY/TutO3XGr55I/AAAAAAAAEqY/OGPhltIA2cM/s640/nooglerkid.jpg" style="border: 1px #777; margin: 0;" alt="My daughter wearing Google hat" title="She loves the hat, BTW."&gt;&lt;/a&gt;&lt;/center&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-4578599640898994150?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=7fYGmHa_Eaw:Zl_cSCNu1OA:Osvv7CGXBvU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=Osvv7CGXBvU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=7fYGmHa_Eaw:Zl_cSCNu1OA:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/7fYGmHa_Eaw" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/4578599640898994150?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/4578599640898994150?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2011/12/ada-initiative-2012.html" title="The Ada Initiative 2012" /><author><name>Denton Gentry</name><uri>https://profiles.google.com/103797409565331693058</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-tdZM5hM_1D0/AAAAAAAAAAI/AAAAAAAAClE/SIaTjGU1fTQ/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-Oa6mVt1-6jA/TutOu9k2tCI/AAAAAAAAEqM/5yzLl-xEDd8/s72-c/adadonate.png" height="72" width="72" /></entry><entry gd:etag="W/&quot;Ak8DRXgyeip7ImA9WhRQF0w.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-9178310715716956225</id><published>2011-12-12T05:15:00.000-08:00</published><updated>2011-12-12T11:41:14.692-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-12T11:41:14.692-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Administrivia" /><title>Go Go Gadget Google Currents!</title><content type="html">&lt;p&gt;Last week &lt;a href="http://googlemobile.blogspot.com/2011/12/google-currents-is-hot-off-press.html"&gt;Google introduced&lt;/a&gt; &lt;a href="http://www.google.com/producer/editions"&gt;Currents&lt;/a&gt;, a publishing and distribution platform for smartphones and tablets. I decided to publish this blog as an edition, and wanted to walk through how it works.&lt;/p&gt;


&lt;br/&gt;&amp;nbsp;&lt;br/&gt;
&lt;h3&gt;Publishing an Edition&lt;/h3&gt;
&lt;p&gt;&lt;img border="0" width="303" height="355" src="http://2.bp.blogspot.com/-SeunLAJyErM/TuX8w0cPbKI/AAAAAAAAEog/SGgsJpSjEyM/s640/producer.png" align="right" style="margin: 0 0 0 1em;" alt="Google Currents producer screenshot" title="Someday I hope to advance to Executive Producer."&gt;Setting up the &lt;a href="http://www.google.com/producer/"&gt;publisher side of Google Currents&lt;/a&gt; was straightforward. I entered data in a few tabs of the interface:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Edition settings:&lt;/b&gt; Entered the name for the blog, and the Google Analytics ID used on the web page.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Sections:&lt;/b&gt; added a "Blog" section, sourced from the RSS feed for this blog. I use &lt;a href="http://feedburner.com/"&gt;Feedburner&lt;/a&gt; to post-process the raw RSS feed coming from Blogger. However I saw no difference in the layout of the articles in Google Currents between Feedburner and the Blogger feed. As Currents provides statistics using Google Analytics, I didn't want to have double counting by having the same users show up in the Feedburner analytics. I went with the RSS feed from Blogger.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Sections-&amp;gt;Blog:&lt;/b&gt; After adding the Blog section I customized its CSS slightly, to use the paper tape image from the blog masthead as a header. I uploaded a 400x50 version of the image to the Media Library, and modified the CSS like so:&lt;/p&gt;
&lt;pre style="font-family: monospace; margin-left: 1em;"&gt;.customHeader {
  background-color: #f5f5f5;
  display: -webkit-box;
  &lt;b&gt;background-image:  url('attachment/CAAqBggKMNPYLDDD3Qc-GoogleCurrentsLogo.jpg');&lt;/b&gt;
  &lt;b&gt;background-repeat: repeat-x;&lt;/b&gt;
  height: &lt;b&gt;50px;&lt;/b&gt;
  -webkit-box-flex: 0;
  -webkit-box-orient: horizontal;
  -webkit-box-pack: center;
}&lt;/pre&gt;

&lt;p&gt;&lt;b&gt;Manage Articles:&lt;/b&gt; I didn't do anything special here. Once the system has fetched content from RSS it is possible to tweak its presentation here, but I doubt I will do that. There is a limit to the amount of time I'll spend futzing.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Media Library:&lt;/b&gt; I uploaded the header graphic to use in the Sections tab.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Grant access:&lt;/b&gt; anyone can read this blog.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Distribute:&lt;/b&gt; I had to click to verify content ownership. As I had already gone through the verification process  for &lt;a href="https://www.google.com/webmasters/tools/"&gt;Google Webmaster Tools&lt;/a&gt;, the Producer verification went through without additional effort. I then clicked "Distribute" and voila!&lt;/p&gt;


&lt;br/&gt;&amp;nbsp;&lt;br clear="right" /&gt;
&lt;h3&gt;The Point?&lt;/h3&gt;
&lt;p&gt;&lt;img border="0" width="391" height="506" src="http://3.bp.blogspot.com/-lgfEb7dnXls/TuX8nSUKiYI/AAAAAAAAEoU/0dNS-8MTRDo/s640/ipadcurrents.png" align="right" style="margin: 0 0 0 1em;" alt="iPad screenshot of this site in Google Currents" title="Yeah, it is an iPad not an Android device. Send me your hate."&gt;Much of the publisher interface concerns formatting and presentation of articles. RSS feeds generally require significant work on the formatting to look reasonable, a service performed by Feedburner and by tools like Flipboard and Google Currents. Nonetheless, I don't think the formatting is the main point, presentation is a means to an end. RSS is a reasonable transport protocol, but people have pressed it into service as the supplier of presentation and layout as well by wrapping a UI around it. Its not very good at it. Publishing tools have to expend effort on presentation and layout to make it useable.&lt;/p&gt;

&lt;p&gt;Nonetheless, for me at least, the main point of publishing to Google Currents is discoverability. I'm hopeful it will evolve into a service which doesn't just show me material I already &lt;i&gt;know&lt;/i&gt; I'm interested in, but also becomes good at suggesting new material which fits my interests.&lt;/p&gt;


&lt;br/&gt;&amp;nbsp;&lt;br/&gt;
&lt;h3&gt;Community Trumps Content&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://www.readwriteweb.com/archives/google_currents_is_to_social_media_as_justin_biebe.php"&gt;A concern has been expressed that content distribution tools&lt;/a&gt; like this, which use web protocols but are not a web page, will kill off the blog comments which motivate many smaller sites to continue publishing. The thing is, in my experience at least, blog comments all but died long ago. Presentation of the content had nothing to do with it: Community trumps Content. That is, people motivated to leave comments tend to gravitate to an online community where they can interact. They don't confine themselves to material from a single site. Only the most &lt;a href="http://avc.com/"&gt;massive blogs&lt;/a&gt; have the gravitational attraction to hold a community together. The rest quickly lose their atmosphere to Reddit/Facebook/Google+/etc. I am grateful when people leave comments on the blog, but I get just as much edification from a comment on a social site, and just as much consternation if the sentiment is negative, as if it is here. It is somewhat more difficult for me to &lt;i&gt;find&lt;/i&gt; comments left on social sites, but let me be perfectly clear: that is &lt;b&gt;my&lt;/b&gt; problem, and my job to stay on top of.&lt;/p&gt;


&lt;br/&gt;&amp;nbsp;&lt;br/&gt;
&lt;h3&gt;The Mobile Web&lt;/h3&gt;
&lt;p&gt;One other finding from setting up Currents: &lt;a href="http://buzz.blogger.com/2011/06/announcing-blogger-mobile-templates.html"&gt;the Blogger mobile templates are quite good.&lt;/a&gt; The formatting of this site in a mobile browser is very nice, and similar to the formatting which Currents comes up with. To me Currents is mostly about discoverability, not just presentation.&lt;/p&gt;


&lt;!-- mjha1667@frumpywizard.com --&gt;
&lt;!-- yitzashim1667 AT frumpywizard.com --&gt;
&lt;!-- magen1667 AT frumpywizard DOT com --&gt;
&lt;!-- tarussov1667 AT GMail --&gt;
&lt;!-- palshi1667.REMOVENOSPAM@frumpywizard.com --&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-9178310715716956225?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=EEkBYs1hKFk:3_RW0Q6uwRQ:Osvv7CGXBvU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=Osvv7CGXBvU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=EEkBYs1hKFk:3_RW0Q6uwRQ:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/EEkBYs1hKFk" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/9178310715716956225?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/9178310715716956225?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2011/12/go-go-gadget-google-currents.html" title="Go Go &lt;strike&gt;Gadget&lt;/strike&gt; Google Currents!" /><author><name>Denton Gentry</name><uri>https://profiles.google.com/103797409565331693058</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-tdZM5hM_1D0/AAAAAAAAAAI/AAAAAAAAClE/SIaTjGU1fTQ/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-SeunLAJyErM/TuX8w0cPbKI/AAAAAAAAEog/SGgsJpSjEyM/s72-c/producer.png" height="72" width="72" /></entry><entry gd:etag="W/&quot;CkEEQXY6fSp7ImA9WhRQEko.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-5144113285331215502</id><published>2011-12-07T07:10:00.000-08:00</published><updated>2011-12-07T07:10:00.815-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-07T07:10:00.815-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Ethernet" /><title>Requiem for Jumbo Frames</title><content type="html">&lt;p&gt;This weekend &lt;a href="https://twitter.com/#!/etherealmind"&gt;Greg Ferro&lt;/a&gt; published &lt;a href="http://etherealmind.com/ethernet-jumbo-frames-full-duplex-9000-bytes/"&gt;an article about jumbo frames&lt;/a&gt;. He points to &lt;a href="http://www.boche.net/blog/index.php/2011/01/24/jumbo-frames-comparison-testing-with-ip-storage-and-vmotion/"&gt;recent measurements showing no real benefit&lt;/a&gt; with large frames. Some years ago I worked on NIC designs, and at the time we talked about Jumbo frames a lot. It was always a tradeoff: improve performance by sacrificing compatibility, or live with the performance until hardware designs could make the 1500 byte MTU be as efficient as jumbo frames. The latter school of thought won out, and they delivered on it. Jumbo frames no longer offer a significant performance advantage.&lt;/p&gt;

&lt;p&gt;Roughly speaking, software overhead for a networking protocol stack can be divided into two chunks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Per-byte&lt;/b&gt; which increases with each byte of data sent. Data copies, encryption, checksums, etc make up this kind of overhead.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Per-packet&lt;/b&gt; which increases with each &lt;u&gt;packet&lt;/u&gt; regardless of how big the packet is. Interrupts, socket buffer manipulation, protocol control block lookups, and context switches are examples of this kind of overhead.&lt;/li&gt;
&lt;/ul&gt;


&lt;br/&gt;&amp;nbsp;&lt;br/&gt;
&lt;h3&gt;Wayback machine to 1992&lt;/h3&gt;
&lt;p&gt;I'm going to talk about the evolution of operating systems and NICs starting from the 1990s, but will focus on Unix systems. DOS and MacOS 6.x were far more common back then, but modern operating systems evolved more similarly to Unix than to those environments.&lt;/p&gt;

&lt;p&gt;&lt;img border="0" width="116" height="130" src="http://1.bp.blogspot.com/-wbBtUU9KGIQ/Tt981w2WLqI/AAAAAAAAEb0/GVPTp5dohMc/s1600/dataflow.png" align="right" style="border: 1px #777; margin: 0 0 0 1em;" alt="Address spaces in user space, kernel, and NIC hardware" title="Three stages to orbit."&gt;Lets consider a typical processing path for sending a packet in a Unix system in the early 1990s:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Application calls write(). System copies a chunk of data into the kernel, to mbufs/mblks/etc.&lt;/li&gt;
&lt;li&gt;Kernel buffers handed to TCP/IP stack, which looks up the protocol control block (PCB) for the socket.&lt;/li&gt;
&lt;li&gt;Stack calculates a TCP checksum and populates the TCP, IP, and Ethernet headers.&lt;/li&gt;
&lt;li&gt;Ethernet driver copies kernel buffers out to the hardware. Programmed I/O using the CPU to copy was quite common in 1992.&lt;/li&gt;
&lt;li&gt;Hardware interrupts when the transmission is complete, allowing the driver to send another packet.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Altogether the data was copied two and a half times: from user space to kernel, from kernel to NIC, plus a pass over the data to calculate the TCP checksum. There were additionally &lt;i&gt;per packet&lt;/i&gt; overheads in looking up the PCB, populating headers, and handling interrupts.&lt;/p&gt;

&lt;p&gt;The receive path was similar, with a NIC interrupt kicking off processing of each packet and two and a half copies up to the receiving application. There was more per-packet overhead for receive: where transmit could look up the PCB once and process a sizable chunk of data from the application in one swoop, RX always gets one packet at a time.&lt;/p&gt;

&lt;p&gt;Jumbo frames were a performance advantage in this timeframe, but not a huge one. Larger frames reduced the per-packet overhead, but the per-byte overheads were significant enough to dominate the performance numbers.&lt;/p&gt;


&lt;br/&gt;&amp;nbsp;&lt;br/&gt;
&lt;h3&gt;Wayback Machine to 1999&lt;/h3&gt;
&lt;p&gt;An early optimization was elimination of the separate pass over the data for the TCP checksum. It could be folded into one of the data copies, and NICs also quickly added hardware support. &lt;i&gt;[Aside: the separate copy and checksum passes in 4.4BSD allowed years of academic papers to be written, putting whatever cruft they liked into the protocol, yet still portraying it as a performance improvement by incidentally folding the checksum into a copy.]&lt;/i&gt; NICs also evolved to be DMA devices; the memory subsystem still had to bear the overhead of the copy to hardware, but the CPU load was alleviated. Finally, operating systems got smarter about leaving gaps for headers when copying data into the kernel, eliminating a bunch of memory allocation overhead to hold the TCP/IP/Ethernet headers.&lt;/p&gt;

&lt;p&gt;&lt;img border="0" width="400" height="260" src="http://1.bp.blogspot.com/-H2yTnmYI5jg/Tt99EqZFFnI/AAAAAAAAEcE/JUyDqAXtp9o/s640/jumbo.png" align="right" style="border: 1px #777; margin: 0 0 0 1em;" alt="Packet size vs throughput in 2000, 2.5x for 9180 byte vs 1500" title="I admit it: until about 1995, I thought ATM was a good idea."&gt;I have data on packet size versus throughput in this timeframe, collected in the last months of 2000. It was gathered for a presentation at &lt;a href="http://www.ieeelcn.org/prior/lcn25program.html"&gt;LCN 2000&lt;/a&gt;. It used an OC-12 ATM interface, where LAN emulation allowed MTUs up to 18 KBytes. I had to find an &lt;b&gt;old&lt;/b&gt; system to run these, the modern systems of the time could almost max out the OC-12 link with 1500 byte packets. I recall it being a Sparcstation-20. The ATM NIC supported TCP checksums in hardware and used DMA.&lt;/p&gt;

&lt;p&gt;Roughly the year 1999 was the peak of when jumbo frames would have been most beneficial. Considerable work had been done by that point to reduce per-byte overheads, eliminating the separate checksumming pass and offloading data movement from the CPU. Some work had been done to reduce the per-packet overhead, but not as much. &lt;i&gt;After&lt;/i&gt; 1999 additional hardware focussed on reducing the per-packet overhead, and jumbo frames gradually became less of a win.&lt;/p&gt;


&lt;br/&gt;&amp;nbsp;&lt;br/&gt;
&lt;h3&gt;LSO/LRO&lt;/h3&gt;
&lt;p&gt;&lt;img border="0" width="94" height="175" src="http://1.bp.blogspot.com/-_RPzaFu6KA4/Tt99ohSt82I/AAAAAAAAEcQ/yglRkaJXSso/s200/lso.png" align="right" style="border: 1px #777; margin: 0 0 0 1em;" alt="Protocol stack handing a chunk of data to NIC" title="Microsoft refers to their accelerated protocol stack as Chimney, so I drew it like a bunch of bricks."&gt;Large Segment Offload (LSO), referred to as TCP Segmentation Offload (TSO) in Linux circles, is a technique to copy a large chunk of data from the application process and hand it as-is to the NIC. The protocol stack generates a single set of Ethernet+TCP+IP header to use as a template, and the NIC handles the details of incrementing the sequence number and calculating fresh checksums for a new header prepended to each packet. Chunks of 32K and 64K are common, so the NIC transmits 21 or 42 TCP segments without further intervention from the protocol stack.&lt;/p&gt;

&lt;p&gt;The interesting thing about LSO and Jumbo frames is that Jumbo frames no longer make a difference. The CPU only gets involved for every large chunk of data, the overhead is the same whether that chunk turns into 1500 byte or 9000 byte packets on the wire. The main impact of the frame size is the number of ACKs coming back, as most TCP implementations generate an ACK for every other frame. Transmitting jumbo frames would reduce the number of ACKs, but that kind of overhead is below the noise floor. We just don't care.&lt;/p&gt;

&lt;p&gt;There is a similar technique for received packets called, imaginatively enough, Large Receive Offload (LRO). For LSO the NIC and protocol software are in control of when data is sent. For LRO, packets just arrive whenever they arrive. The NIC has to gather packets from each flow to hand up in a chunk. Its quite a bit more complex, and doesn't tend to work as well as LSO. As modern web application servers tend to send far more data than they receive, LSO has been of much greater importance than LRO.&lt;/p&gt;

&lt;p&gt;Large Segment Offload mostly removed the justification for jumbo frames. Nonetheless support for larger frame sizes is almost universal in modern networking gear, and customers who were already using jumbo frames have generally carried on using them. Moderately larger frame support is also helpful for carriers who want to encapsulate customer traffic within their own headers. I expect hardware designs to continue to accommodate it.&lt;/p&gt;


&lt;br/&gt;&amp;nbsp;&lt;br/&gt;
&lt;h3&gt;TCP Calcification&lt;/h3&gt;
&lt;p&gt;There has been a big downside of pervasive use of LSO: it has become the immune response preventing changes in protocols. NIC designs vary widely in their implementation of the technique, and some of them are very rigid. Here &amp;quot;rigid&amp;quot; is a euphemism for &amp;quot;mostly crap.&amp;quot; There are NICs which hard-code how to handle protocols as they existed in the early part of this century: Ethernet header, optional VLAN header, IPv4/IPv6, TCP. Add any new option, or any new header, and some portion of existing NICs will not cope with it. Making changes to existing protocols or adding new headers is vastly harder now, as changes are likely to throw the protocol back into the slow zone and render moot any of the benefits it brings.&lt;/p&gt;

&lt;p&gt;It used to be that any new TCP extension had to carefully negotiate between sender and receiver in the SYN/SYN+ACK to make sure both sides would support an option. Nowadays due to LSO and to the pervasive use of middleboxes, we basically cannot add options to TCP at all.&lt;/p&gt;

&lt;p&gt;I guess the moral is, &lt;i&gt;&amp;quot;be careful what you wish for.&amp;quot;&lt;/i&gt;&lt;/p&gt;

&lt;!-- mjha1667@frumpywizard.com --&gt;
&lt;!-- yitzashim1667 AT frumpywizard.com --&gt;
&lt;!-- magen1667 AT frumpywizard DOT com --&gt;
&lt;!-- tarussov1667 AT GMail --&gt;
&lt;!-- palshi1667.REMOVENOSPAM@frumpywizard.com --&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-5144113285331215502?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=Qrn61EzmIhY:r0n5vilRrcE:Osvv7CGXBvU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=Osvv7CGXBvU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=Qrn61EzmIhY:r0n5vilRrcE:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/Qrn61EzmIhY" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/5144113285331215502?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/5144113285331215502?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2011/12/requiem-for-jumbo-frames.html" title="Requiem for Jumbo Frames" /><author><name>Denton Gentry</name><uri>https://profiles.google.com/103797409565331693058</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-tdZM5hM_1D0/AAAAAAAAAAI/AAAAAAAAClE/SIaTjGU1fTQ/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-wbBtUU9KGIQ/Tt981w2WLqI/AAAAAAAAEb0/GVPTp5dohMc/s72-c/dataflow.png" height="72" width="72" /></entry><entry gd:etag="W/&quot;C04ERnY5eCp7ImA9WhRRFUk.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-6977564783172918815</id><published>2011-11-28T06:32:00.001-08:00</published><updated>2011-11-28T20:45:07.820-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-28T20:45:07.820-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Ethernet" /><title>QFabric Followup</title><content type="html">&lt;p&gt;In August this site &lt;a href="http://codingrelic.geekhold.com/2011/08/making-stuff-up-about-qfabric.html"&gt;published&lt;/a&gt; &lt;a href="http://codingrelic.geekhold.com/2011/08/backplane-goes-to-eleven.html"&gt;a series&lt;/a&gt; &lt;a href="http://codingrelic.geekhold.com/2011/08/qfabric-flow-control-considered-harmful.html"&gt;of posts&lt;/a&gt; &lt;a href="http://codingrelic.geekhold.com/2011/08/qfabric-conclusion.html"&gt;about&lt;/a&gt; the &lt;a href="http://www.juniper.net/us/en/company/press-center/press-releases/2011/pr_2011_02_23-13_04.html"&gt;Juniper QFabric&lt;/a&gt;. Since then Juniper has &lt;a href="http://www.juniper.net/techpubs/en_US/release-independent/junos/information-products/pathway-pages/hardware/qfx-series/qfx3000.html"&gt;released hardware documentation&lt;/a&gt; for the QFabric components, so its time for a followup.&lt;/p&gt;

&lt;p&gt;&lt;img border="0" width="313" height="158" align="right" src="http://4.bp.blogspot.com/-RBOkG61Y5X8/TtObU8iXsiI/AAAAAAAADfE/pMcEzTy34WM/s320/qfabric.png" style="border: none; margin: 1em 0 1em 1em;" alt="QF edge Nodes, Interconnects, and Directors" title="It looks a bit like a suspension bridge."&gt;QFabric consists of Nodes at the edges wired to large Interconnect switches in the core. The whole collection is monitored and managed by out of band Directors. Juniper emphasizes that the QFabric should be thought of as a single distributed switch, not as a network of individual switches. The entire QFabric is managed as one entity.&lt;/p&gt;

&lt;p&gt;&lt;img border="0" width="436" height="161" align="right" src="http://4.bp.blogspot.com/-XvO5miTqg6U/TtObfngv-yI/AAAAAAAADfQ/VZXWisEgjN0/s640/modid.png" style="border: none; margin: 1em 0 1em 1em;" alt="Control header prepended to frame" title="There is no problem which cannot be solved by an additional layer of indirection."&gt;The fundamental distinction between QFabric and conventional switches is in the forwarding decision. In a conventional switch topology each layer of switching looks at the L2/L3 headers to figure out what to do. The edge switch sends the packet to the distribution switch, which examines the headers again before sending the packet on towards the core (which examines the headers again). QFabric does not work this way. &lt;a href="http://codingrelic.geekhold.com/2011/08/making-stuff-up-about-qfabric.html"&gt;QFabric functions much more like the collection of switch chips inside a modular chassis&lt;/a&gt;: the forwarding decision is made by the ingress switch and is conveyed through the rest of the fabric by prepending control headers. The Interconnect and egress Node forward the packet according to its control header, not via another set of L2/L3 lookups.&lt;/p&gt;


&lt;br/&gt;&amp;nbsp;&lt;br/&gt;
&lt;h3&gt;Node Groups&lt;/h3&gt;
&lt;p&gt;The &lt;a href="http://www.juniper.net/techpubs/en_US/release-independent/junos/information-products/pathway-pages/hardware/qfx-series/qfx3000.html"&gt;Hardware Documentation&lt;/a&gt; describes two kinds of Node Groups, Server and Network, which gather multiple edge Nodes together for common purposes.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Server Node Groups are straightforward: normally the edge Nodes are independent, connecting servers and storage to the fabric. Pairs of edge switches can be configured as Server Node Groups for redundancy, allowing LAG groups to span the two switches.&lt;/li&gt;
&lt;li&gt;Network Node Groups configure up to eight edge Nodes to interconnect with remote networks. Routing protocols like BGP or OSPF run on the Director systems, so the entire Group shares a common Routing Information Base and other data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why have Groups? Its somewhat easier to understand the purpose of the Network Node Group: routing processes have to be spun up on the Directors, and perhaps those processes have to point to some distinct entity to operate with. Why have Server Node Groups, though? Redundant server connections are certainly beneficial, but why require an additional fabric configuration to allow it?&lt;/p&gt;

&lt;p&gt;&lt;img border="0" width="216" height="89" align="right" src="http://4.bp.blogspot.com/-2gJ5y_atVok/TtOePnYSQbI/AAAAAAAADf0/rNwL44Fc3qs/s320/LAG.png" style="border: none; margin: 0 0 1em 1em;" alt="Ingress fanout to four LAG member ports" title="Four years of EE classes just so I can draw a trapezoid as a mux."&gt;I don't know the answer, but I suspect it has to do with Link Aggregation (LAG). Server Node Groups allow a LAG to be configured using ports spanning the two Nodes. In a chassis switch, LAG is handled by the ingress chip. It looks up the destination address to find the destination port. Every chip knows the membership of all LAGs in the chassis. The ingress chip computes a hash of the packet to pick which LAG member port to send the packet to. This is how LAG member ports can be on different line cards, the ingress port sends it to the correct card.&lt;/p&gt;

&lt;p&gt;&lt;img border="0" width="211" height="175" align="right" src="http://4.bp.blogspot.com/-m5uOPhYW0-w/TtObw6gvqBI/AAAAAAAADfo/KSkvBIAuwa0/s320/InterconnectLAG.png" style="border: none; margin: 0 0 1em 1em;" alt="Ingress fanout to four LAG member ports" title="Four years of EE classes just so I can draw a trapezoid as a mux."&gt;The downside of implementing LAG at ingress is that &lt;i&gt;every chip&lt;/i&gt; has to know the membership of all LAGs in the system. Whenever a LAG member port goes down, &lt;i&gt;all&lt;/i&gt; chips have to be updated to stop using it. With QFabric, where ingress chips are distributed across a network and the largest fabric could have thousands of server LAG connections, updating all of the Nodes whenever a link goes down could take a really long time. LAG failure is supposed to be quick, with minimal packet loss when a link fails. Therefore I wonder if Juniper has implemented LAG a bit differently, perhaps by handling member port selection in the Interconnect, in order to minimize the time to handle a member port failure.&lt;/p&gt;

&lt;p&gt;I feel compelled to emphasize again: I'm making this up. I don't know how QFabric is implemented nor why Juniper made the choices they made. Its just fun to speculate.&lt;/p&gt;


&lt;br/&gt;&amp;nbsp;&lt;br/&gt;
&lt;h3&gt;Virtualized Junos&lt;/h3&gt;
&lt;p&gt;Regarding the Director software, the &lt;a href="http://www.juniper.net/techpubs/en_US/junos11.3/topics/concept/director-group-qfabric-understanding.html"&gt;Hardware Documentation&lt;/a&gt; says, &lt;i&gt;&amp;quot;[Director devices] run the Junos operating system (Junos OS) on top of a CentOS foundation.&amp;quot;&lt;/i&gt; Now &lt;b&gt;that&lt;/b&gt; is an interesting choice. Way, way back in the mists of time, Junos started from &lt;a href="http://www.netbsd.org/"&gt;NetBSD&lt;/a&gt; as its base OS. NetBSD is still a viable project and runs on modern x86 machines, yet Juniper chose to hoist Junos atop a Linux base instead.&lt;/p&gt;

&lt;p&gt;I suspect that in the intervening time, the Junos kernel and platform support diverged so far from NetBSD development that it became impractical to integrate recent work from the public project. Juniper would have faced a substantial effort to handle modern x86 hardware, and chose instead to virtualize the Junos kernel in a VM whose hardware was easier to support. I'll bet the CentOS on the Director is the host for a &lt;a href="http://xen.org/"&gt;Xen hypervisor&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Update:&lt;/b&gt; in the comments, &lt;a href="http://twitter.com/#!/brandonrbennett"&gt;Brandon Bennett&lt;/a&gt; and &lt;a href="http://twitter.com/#!/LapTop006"&gt;Julien Goodwin&lt;/a&gt; both note that Junos used &lt;a href="http://www.freebsd.org/"&gt;FreeBSD&lt;/a&gt; as its base OS, not &lt;a href="http://www.netbsd.org/"&gt;NetBSD&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Aside: with network OSes developed in the last few years, companies have tended to put effort into keeping the code portable enough to run on a regular x86 server. The development, training, QA, and testing benefits of being able to run on a regular server are substantial. That means implementing a proper hardware abstraction layer to handle running on a platform which doesn't have the fancy switching silicon. In the 1990s when Junos started, running on x86 was not common practice. We tended to do development on Sparcstations, DECstations, or some other fancy RISC+Unix machine and didn't think much about Intel. The RISC systems were so expensive that one would never outfit a rack of them for QA, it was cheaper to build a bunch of switches instead.&lt;/p&gt;

&lt;p&gt;Aside, redux: &lt;a href="http://www.juniper.net/as/en/products-services/software/junos-platform/junosphere/"&gt;Junosphere&lt;/a&gt; also runs Junos as a virtual machine. In a company the size of Juniper these are likely to have been separate efforts, which might not even have known about each other at first. Nonetheless the timing of the two products is close enough that there may have been some cross-group pollination and shared underpinnings.&lt;/p&gt; 


&lt;br/&gt;&amp;nbsp;&lt;br/&gt;
&lt;h3&gt;Misc Notes&lt;/h3&gt;
&lt;ul&gt;
 &lt;li&gt;The Director communicates with the Interconnects and Nodes via a separate control network, handled by Juniper's previous generation EX4200. This is an example of &lt;a href="http://codingrelic.geekhold.com/2011/10/well-trodden-technology-paths.html"&gt;using a simpler network&lt;/a&gt; to bootstrap and control a more complex one.&lt;/li&gt;
 &lt;li&gt;QFX3500 has four QSFPs for 40 gig Ethernet. These can each be broken out into four 10G Ethernet ports, except the first one which supports only three 10G ports. That is &lt;u&gt;fascinating.&lt;/u&gt; I wonder what the fourth one does?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thats all for now. We may return to QFabric as it becomes more widely deployed or as additional details surface.&lt;/p&gt;


&lt;br/&gt;
&lt;p style="font-size: 90%; color: #777; font-style: italic;"&gt;footnote: this blog contains articles on a range of topics. If you want more posts like this, I suggest the &lt;a href="http://codingrelic.geekhold.com/search/label/Ethernet"&gt;Ethernet&lt;/a&gt; label.&lt;/p&gt;

&lt;!-- mjha1667@frumpywizard.com --&gt;
&lt;!-- yitzashim1667 AT frumpywizard.com --&gt;
&lt;!-- magen1667 AT frumpywizard DOT com --&gt;
&lt;!-- tarussov1667 AT GMail --&gt;
&lt;!-- palshi1667.REMOVENOSPAM@frumpywizard.com --&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-6977564783172918815?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=d6LIYmU0MiQ:a09x---NAtg:Osvv7CGXBvU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=Osvv7CGXBvU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=d6LIYmU0MiQ:a09x---NAtg:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/d6LIYmU0MiQ" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/6977564783172918815?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/6977564783172918815?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2011/11/qfabric-followup.html" title="QFabric Followup" /><author><name>Denton Gentry</name><uri>https://profiles.google.com/103797409565331693058</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-tdZM5hM_1D0/AAAAAAAAAAI/AAAAAAAAClE/SIaTjGU1fTQ/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-RBOkG61Y5X8/TtObU8iXsiI/AAAAAAAADfE/pMcEzTy34WM/s72-c/qfabric.png" height="72" width="72" /></entry><entry gd:etag="W/&quot;C0AMR34-cSp7ImA9WhRREEo.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-199724273362324735</id><published>2011-11-23T06:31:00.000-08:00</published><updated>2011-11-23T10:09:46.059-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-23T10:09:46.059-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Ethernet" /><title>Unnatural BGP</title><content type="html">&lt;p&gt;Last week &lt;a href="http://yuba.stanford.edu/~casado/"&gt;Martin Casado&lt;/a&gt; published some thoughts about using &lt;a href="http://networkheresy.wordpress.com/2011/11/17/is-openflowsdn-good-at-forwarding/"&gt;OpenFlow and Software Defined Networking for simple forwarding&lt;/a&gt;. That is, does SDN help in distributing shortest path routes for IP prefixes? BGP/OSPF/IS-IS/etc are pretty good for this, with the added benefit of being fully distributed and thoroughly debugged.&lt;/p&gt;

&lt;p&gt;The &lt;a href="http://networkheresy.wordpress.com/2011/11/17/is-openflowsdn-good-at-forwarding/"&gt;full article&lt;/a&gt; is worth a read. The summary (which Martin himself supplied) is &lt;i&gt;&amp;quot;I find it very difficult to argue that SDN has value when it comes to providing simple connectivity.&amp;quot;&lt;/i&gt; Existing routing protocols are quite good at distributing shortest path prefix routes, the real value of SDN is in handling more complex behaviors.&lt;/p&gt;

&lt;p&gt;To expand on this a bit, there have been various efforts over the years to tailor forwarding behavior using more esoteric cost functions. The monetary cost of using a link is a common one to optimize for, as it provides justification for spending on a development effort and also because the business arrangements driving the pricing tend not to distill down to simple weights on a link. Providers may want to keep their customer traffic off of competing networks who are in a position to steal the customer. Transit fees may kick in if a peer delivers significantly more traffic than it receives, providing an incentive to preferentially send traffic through a peer in order to keep the business arrangement equitable. Many of these examples are covered in &lt;a href="http://docs.google.com/viewer?url=http%3A%2F%2Fwww.cs.princeton.edu%2Fcourses%2Farchive%2Ffall06%2Fcos561%2Fslides%2F14bgp-policy.ppt"&gt;slides from a course&lt;/a&gt; by &lt;a href="http://www.cs.princeton.edu/~jrex/"&gt;Jennifer Rexford&lt;/a&gt;, who spent several years working on such topics at &lt;a href="http://www.research.att.com/"&gt;AT&amp;amp;T Research&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img border="0" width="273" height="141" src="http://3.bp.blogspot.com/-wLFYow3J1UY/Tsqm4kyQO5I/AAAAAAAADag/wnoQ2KMkA9A/s320/BGP.png" align="right" style="border: none; margin: 0 0 0 1em;" alt="BGP peering between routers at low weight, from each router to controller at high weight" title="Its a whirling shield of BGP peers."&gt;Until quite recently these systems had to be constructed using a standard routing protocol, because that is what the routers would support. BGP is a reasonable choice for this because its interoperability between modern implementations is excellent. The optimization system would peer with the routers, periodically recompute the desired behavior, and export those choices as the best route to destinations. To avoid having the Optimizer be a single point of failure able to bring down the entire network, the routers would retain peering connections with each other at a low weight as a fallback. The fallback routes would never be used so long as the Optimizer routes are present.&lt;/p&gt;

&lt;p&gt;This works. It solves real problems. However it is hard to ignore the fact that BGP &lt;b&gt;adds no value&lt;/b&gt; in the implementation of the optimization system. Its just an obstacle in the way of getting entries into the forwarding tables of the switch fabric. It also constrains the forwarding behaviors to those which BGP can express, generally some combination of destination address and QoS.&lt;/p&gt;

&lt;p&gt;&lt;img border="0" width="265" height="150" src="http://4.bp.blogspot.com/-R_7wvAOjCFU/TsqnSxL0PTI/AAAAAAAADas/Pe8xZJtJ40E/s320/SDN.png" align="right" style="border: none; margin: 0 0 0 1em;" alt="BGP peering between routers, SDN to controller" title="You can no longer see the router for all the protocols."&gt;Product support for software defined networking is &lt;a href="http://techfieldday.com/2011/nec-presents-networking-tech-field-day-2/"&gt;now&lt;/a&gt; &lt;a href="http://www.juniper.net/us/en/company/press-center/press-releases/2011/pr_2011_10_26-06_42.html"&gt;appearing&lt;/a&gt; &lt;a href="http://blogs.cisco.com/datacenter/whats-new-with-cisco-and-openflow/"&gt;in the market&lt;/a&gt;. These are generally parallel control paths alongside the existing routing protocols. SDN deposits routes into the same forwarding tables as BGP and OSPF, with some priority or precedence mechanism to control arbitration.&lt;/p&gt;

&lt;p&gt;By using an SDN protocol these optimization systems are no longer constrained to what BGP can express, they can operate on any information which the hardware supports. Yet even here there is an awkward interaction with the other protocols. Its useful to keep the peering connections with other routers as a fallback in case of controller failure, but they are not well integrated. We can only set precedences between SDN and BGP and hope for the best.&lt;/p&gt;

&lt;p&gt;I do wonder if the existing implementation of routing protocols needs a more significant rethink. There is great value in retaining compatibility with the external interfaces: being able to peer with existing BGP/OSPF/etc nodes is a huge benefit. In contrast, there is little value to retaining the internal implementation choices inside the router. The existing protocols could be made to cooperate more flexibly with other inputs. More speculatively, extensions to the protocol itself could label routes which are expected to be overridden by another source, and only present as a fallback path.&lt;/p&gt;

&lt;!-- mjha1667@frumpywizard.com --&gt;
&lt;!-- yitzashim1667 AT frumpywizard.com --&gt;
&lt;!-- magen1667 AT frumpywizard DOT com --&gt;
&lt;!-- tarussov1667 AT GMail --&gt;
&lt;!-- palshi1667.REMOVENOSPAM@frumpywizard.com --&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-199724273362324735?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=hrJYnHV2WXo:YcCY_nIx86U:Osvv7CGXBvU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=Osvv7CGXBvU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=hrJYnHV2WXo:YcCY_nIx86U:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/hrJYnHV2WXo" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/199724273362324735?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/199724273362324735?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2011/11/unnatural-acts-of-bgp.html" title="Unnatural BGP" /><author><name>Denton Gentry</name><uri>https://profiles.google.com/103797409565331693058</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-tdZM5hM_1D0/AAAAAAAAAAI/AAAAAAAAClE/SIaTjGU1fTQ/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-wLFYow3J1UY/Tsqm4kyQO5I/AAAAAAAADag/wnoQ2KMkA9A/s72-c/BGP.png" height="72" width="72" /></entry><entry gd:etag="W/&quot;CUQAQn8zcSp7ImA9WhRSEkU.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-2869435290368991383</id><published>2011-11-14T05:53:00.001-08:00</published><updated>2011-11-14T07:09:03.189-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-14T07:09:03.189-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Ethernet" /><title>The Computer is the Network</title><content type="html">&lt;p&gt;Modern commodity switch fabric chips are amazingly capable, but their functionality is not infinite. In particular their parsing engines are generally fixed function, extracting information from the set of headers they were designed to process. Similarly the ability to modify packets is constrained to specifically designed in protocols, not an infinitely programmable rewrite engine.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://pomi.stanford.edu/content.php?page=research&amp;subpage=openflow"&gt;Software defined networks&lt;/a&gt; are a wonderful thing, but development of an SDN agent to drive an existing ASIC does not suddenly make it capable of packet handling it wasn't already designed to do. At best, it might expose functions of which the hardware was always capable but had not been utilized by the older software. Yet even that is questionable: once a platform goes into production, the expertise necessary to thoroughly test and develop bug workarounds for ASIC functionality rapidly disperses to work on new designs. If part of the functionality isn't ready at introduction it is often removed from the documentation and retargeted as a feature of the next chip.&lt;/p&gt;


&lt;br/&gt;&amp;nbsp;&lt;br/&gt;
&lt;h3&gt;Decisions at the Edge&lt;/h3&gt;
&lt;p&gt;MPLS networks have an interesting philosophy: the switching elements at the core are conceptually simple, driven by a label stack prepended to the packet. Decisions are made at the edge of the network wherever possible. The core switches may have complex functionality dealing with fast reroutes or congestion management, but they avoid having to re-parse the payloads and make new forwarding decisions.&lt;/p&gt;

&lt;p&gt;Ethernet switches have mostly not followed this philosophy, in fact we've essentially followed the opposite path. We've tended to design in features and capacity at the same time. Larger switch fabrics with more capacity also tend to have more features. Initially this happened because a chip with more ports required a larger silicon die to have room for all of the pins. Thus, there was more room for digital logic. Vendors have accentuated this in their marketing plans, omitting software support for features in "low end" edge switches even if they use the same chipset as the more featureful aggregation products.&lt;/p&gt;

&lt;p&gt;This leaves software defined networking in a bit of a quandary. The MPLS model is simpler to reason about for large collections of switches, you don't have a combinatorial explosion of decision-making at each hop in the forwarding. Yet non-MPLS Ethernet switches have mostly not evolved in that way, and the edge switches don't have the capability to make all of the decisions for behaviors we might want.&lt;/p&gt;


&lt;br/&gt;&amp;nbsp;&lt;br/&gt;
&lt;h3&gt;Software Switches to the Rescue&lt;/h3&gt;
&lt;p&gt;A number of market segments have gradually moved to a model where the first network element to touch the packet is  implemented mostly in software. This allows the hope of substantially increasing their capability. A few examples:&lt;/p&gt;

&lt;img border="0" width="131" height="84" src="http://2.bp.blogspot.com/-Jd8Gs5bGeRk/TsEfesY45sI/AAAAAAAADX8/kd41obJ2TE8/s160/vswitch.png" align="right" style="border: 1px #777; margin: 0 0 0 1em;" alt="vswitch running in the Hypervisor" title="Why the world does the Nexus 1000v have a CLI?"&gt;
&lt;p&gt;&lt;b&gt;Datacenters&lt;/b&gt;: The first hop is a software switch running in the Hypervisor, like the &lt;a href="http://www.vmware.com/products/vnetwork-distributed-switch/overview.html"&gt;VMware vSwitch&lt;/a&gt; or &lt;a href="http://www.cisco.com/en/US/products/ps9902/index.html"&gt;Cisco Nexus 1000v&lt;/a&gt;.&lt;/p&gt;

&lt;br clear="right"/&gt;
&lt;img border="0" width="117" height="84" src="http://2.bp.blogspot.com/-EaurBFbbK6k/TsElJuoJxOI/AAAAAAAADYI/2q5BO8MELe4/s160/WAN.png" align="right" style="border: 1px #777; margin: 0 0 0 1em;" alt="WAN Optimizer with 4 CPUs" title="Yes folks, most of them are just PCs."&gt;
&lt;p&gt;&lt;b&gt;Wide Area Networks&lt;/b&gt;: WAN optimizers have become quite popular because they save money by reducing the amount of traffic sent over the WAN. These are mostly software products at this point, implementing protocol-specific compression and deduplication. Forthcoming 10 Gig products from &lt;a href="http://www.infineta.com/"&gt;Infineta&lt;/a&gt; appear to be the &lt;a href="http://packetpushers.net/show-60-introducing-infineta-hyper-scale-wan-optimization/"&gt;first products containing significant amounts of custom hardware&lt;/a&gt;.&lt;/p&gt;

&lt;br clear="right"/&gt;
&lt;img border="0" width="100" height="84" src="http://2.bp.blogspot.com/-_UA8nQ0yjMU/TsElR1iG6wI/AAAAAAAADYU/62ZvRPp1ImA/s160/WifiAP.png" align="right" style="border: 1px #777; margin: 0 0 0 1em;" alt="Wifi AP with CPU, Wifi MAC, and Ethernet MAC" title="Like the TV antenna? I drew it myself."&gt;
&lt;p&gt;&lt;b&gt;Wifi Access Points&lt;/b&gt;: Traditional, thick APs as seen in the consumer and carrier-provided equipment market are a  CPU with Ethernet and Wifi, forwarding packets in software.&lt;br/&gt;
Thin APs for Enterprise use as deployed by &lt;a href="http://www.arubanetworks.com/"&gt;Aruba&lt;/a&gt;/Airespace/etc are rather different, the real forwarding happens in hardware back at a central controller.&lt;/p&gt;

&lt;br clear="right"/&gt;
&lt;img border="0" width="90" height="84" src="http://2.bp.blogspot.com/-jDAoc3O8D7k/TsElawH1gCI/AAAAAAAADYg/H9Bv254Y18M/s160/cablemodem.png" align="right" style="border: 1px #777; margin: 0 0 0 1em;" alt="Cable modem with DOCSIS and Ethernet" title="I resisted the urge to draw it sitting on a TV."&gt;
&lt;p&gt;&lt;b&gt;Carrier Network Access Units&lt;/b&gt;: Like Wifi APs, access gear for DSL and DOCSIS networks is usually a CPU with the appropriate peripherals and forwards frames in software.&lt;/p&gt;

&lt;br clear="right"/&gt;
&lt;img border="0" width="87" height="87" src="http://2.bp.blogspot.com/-ciwB_pd67I0/TsElhvr--rI/AAAAAAAADYs/xmCGEJ9E4e4/s160/enterprise.png" align="right" style="border: 1px #777; margin: 0 0 0 1em;" alt="Enterprise switch with CPU handling all packets, and a big red X through it" title="There is much bitterness in this picture."&gt;
&lt;p&gt;&lt;b&gt;Enterprise&lt;/b&gt;: Just kidding, the Enterprise is still firmly in the "more hardware == more better" category. Most of the problems to be solved in Enterprise networking today deal with access control, security, and malware containment. Though CPU forwarding at the edge is one solution to that (attempted by ConSentry and Nevis, among others), the industry mostly settled on &lt;a href="http://en.wikipedia.org/wiki/Network_Access_Control"&gt;out of band approaches&lt;/a&gt;.&lt;/p&gt;


&lt;br/&gt;&amp;nbsp;&lt;br/&gt;
&lt;h3&gt;The Computer is the Network&lt;/h3&gt;
&lt;p&gt;The Sun Microsystems tagline through most of the 1980s was &lt;i&gt;&lt;a href="http://thenetworkisthecomputer.com/"&gt;The Network is the Computer&lt;/a&gt;.&lt;/i&gt; At the time it referred to client-server computing like NFS and RPC, though the modern web has made this a reality for many people who spend most of their computing time with social and communication applications via the web. Its a shame that Sun itself didn't live to see the day.&lt;/p&gt;

&lt;p&gt;We're now entering an era where the Computer is the Network. We don't want to depend upon the end-station itself to mark its packets appropriately, mainly due to security and malware considerations, but we want the flexibility of having software touch every packet. Market segments which provide that capability, like datacenters, WAN connections, and even service providers, are going to be a lot more interesting in the next several years.&lt;/p&gt;

&lt;!-- mjha1667@frumpywizard.com --&gt;
&lt;!-- yitzashim1667 AT frumpywizard.com --&gt;
&lt;!-- magen1667 AT frumpywizard DOT com --&gt;
&lt;!-- tarussov1667 AT GMail --&gt;
&lt;!-- palshi1667.REMOVENOSPAM@frumpywizard.com --&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-2869435290368991383?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=S0xZdZyPlBs:ZAOqPZ_Twbs:Osvv7CGXBvU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=Osvv7CGXBvU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=S0xZdZyPlBs:ZAOqPZ_Twbs:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/S0xZdZyPlBs" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/2869435290368991383?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/2869435290368991383?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2011/11/computer-is-network.html" title="The Computer is the Network" /><author><name>Denton Gentry</name><uri>https://profiles.google.com/103797409565331693058</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-tdZM5hM_1D0/AAAAAAAAAAI/AAAAAAAAClE/SIaTjGU1fTQ/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-Jd8Gs5bGeRk/TsEfesY45sI/AAAAAAAADX8/kd41obJ2TE8/s72-c/vswitch.png" height="72" width="72" /></entry><entry gd:etag="W/&quot;DkQESX4-fyp7ImA9WhdaGE4.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-7404049884447783953</id><published>2011-10-28T07:07:00.000-07:00</published><updated>2011-10-28T13:38:28.057-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-28T13:38:28.057-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="social" /><category scheme="http://www.blogger.com/atom/ns#" term="Ethernet" /><title>Tweetflection Point</title><content type="html">&lt;p&gt;Last week at the &lt;a href="http://www.web2summit.com/"&gt;Web 2.0 Summit in San Francisco&lt;/a&gt;, Twitter CEO Dick Costolo talked about recent growth in the service and how iOS5 had caused a &lt;a href="http://techcrunch.com/2011/10/17/twitter-is-at-250-million-tweets-per-day/"&gt;sudden 3x jump in signups&lt;/a&gt;. He also said daily Tweet volume had reached 250 million. There are many, many estimates of the volume of Tweets sent, but I know of only three which are verifiable as directly from Twitter:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;50M tweets/day in March, 2010 &lt;a href="http://blog.twitter.com/2011/03/numbers.html"&gt;according to a Twitter blog post&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;140M tweets/day in March, 2011 &lt;a href="http://blog.twitter.com/2011/03/numbers.html"&gt;according to that same Twitter blog post&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;250M tweets/day in late October, 2011 &lt;a href="http://techcrunch.com/2011/10/17/twitter-is-at-250-million-tweets-per-day/"&gt;according to Dick Costolo&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Graphing these on a log scale shows the &lt;i&gt;rate of growth&lt;/i&gt; in Tweet volume, &lt;strike&gt;roughly tripling in two years&lt;/strike&gt; almost tripling in one year.&lt;/p&gt;

&lt;center&gt;&lt;img border="0" width="640" height="363" src="http://3.bp.blogspot.com/-v2eTchTOCBk/Tqqm7inE2TI/AAAAAAAADLU/irznL-P6kNY/s640/datapoints.png" style="border: 1px #777; margin: 1em 0 1em 0;" alt="Graph of average daily Tweet volume" title="Four data points + much handwaving == blog post!"&gt;&lt;/center&gt;

&lt;p&gt;This graph is misleading though, as we have so few data points. It is very likely that, like signups for the service, the rate of growth in tweet volume suddenly increased after iOS5 shipped. Lets assume the &lt;i&gt;rate of growth&lt;/i&gt; also tripled for the few days after the iOS5 launch, and zoom in on the tail end of the graph. It is quite similar up until a sharp uptick at the end.&lt;/p&gt;

&lt;center&gt;&lt;img border="0" width="640" height="363" src="http://3.bp.blogspot.com/-VO39BPBKyfw/TqqnDkPVFnI/AAAAAAAADLg/htx2jc2NgH0/s640/speculation.png" style="border: 1px #777; margin: 1em 0 1em 0;" alt="Speculative graph of average daily Tweet volume, knee of curve at iOS5 launch." title="Four data points + one made up data point + much handwaving == blog post!"&gt;&lt;/center&gt;

&lt;p&gt;The reality is somewhere between those two graphs, but likely still steep enough to be &lt;b&gt;terrifying&lt;/b&gt; to the engineers involved. iOS5 will absolutely have an impact on the daily volume of Tweets, it would be ludicrous to think otherwise. It probably isn't so abrupt a knee in the curve as shown here, but it has to be substantial. Tweet growth is on a new and steeper slope now. It used to triple in a bit over a year, now it will triple in way less than one year.&lt;/p&gt;

&lt;br/&gt;&amp;nbsp;&lt;br/&gt;
&lt;h3&gt;Why this matters&lt;/h3&gt;
&lt;p&gt;Even five months ago, the traffic to carry the Twitter Firehose &lt;a href="http://codingrelic.geekhold.com/2011/05/dont-cross-tweetstreams.html"&gt;was becoming a challenge to handle&lt;/a&gt;. At that time the average throughput was 35 Mbps, with spikes up to about 138 Mbps. Scaling those numbers to today would be 56 Mbps sustained with spikes to 223 Mbps, and about one year until the spikes exceed a gigabit.&lt;/p&gt;

&lt;p&gt;The indications I've seen are that the feed from Twitter is still sent uncompressed. Compressing using gzip (or &lt;a href="http://code.google.com/p/snappy/"&gt;Snappy&lt;/a&gt;) would gain some breathing room, but not solve the underlying problem. The underlying problem is that the volume of data is increasing way, way faster than the capacity of the network and computing elements tasked with handling it. Compression can reduce the absolute number of bits being sent (at the cost of even more CPU), but not reduce the &lt;i&gt;rate of growth.&lt;/i&gt;&lt;/p&gt;

&lt;p&gt;Fundamentally, there is a limit to how fast a single HTTP stream can go. As described in the &lt;a href="http://codingrelic.geekhold.com/2011/05/dont-cross-tweetstreams.html"&gt;post earlier this year&lt;/a&gt;, we've scaled network and CPU capacity by going horizontal and spreading load across more elements. Use of a single very fast TCP flow restricts the handling to a single network link and single CPU in a number of places. The network capacity has some headroom still, particularly by throwing money at it in the form of 10G Ethernet links. The capacity of a single CPU core to process the TCP stream is the more serious bottleneck. At some point relatively soon it will be more cost effective to split the Twitter firehose across multiple TCP streams, for easier scaling. The Tweet ID (or a new sequence number) could put tweets back into an absolute order when needed.&lt;/p&gt;

&lt;center&gt;&lt;img border="0" width="463" height="91" src="http://1.bp.blogspot.com/-Fhs4a7JxkxI/TqnmrEkdABI/AAAAAAAADKc/4icpnE8UQ5E/s640/unbalanced.png" style="border: 1px #777; margin: 1em 0 1em 0;" alt="Unbalanced link aggregation with a single high speed HTTP firehose." title="It looks like a tartan. Clearly a Scottish network."&gt;&lt;/center&gt;

&lt;br/&gt;

&lt;p&gt;&lt;b&gt;Update:&lt;/b&gt; My math was off. Even before the iOS5 announcement, the rate of growth was nearly tripling in one year. Corrected post.&lt;/p&gt;

&lt;!-- mjha1667@frumpywizard.com --&gt;
&lt;!-- yitzashim1667 AT frumpywizard.com --&gt;
&lt;!-- magen1667 AT frumpywizard DOT com --&gt;
&lt;!-- tarussov1667 AT GMail --&gt;
&lt;!-- palshi1667.REMOVENOSPAM@frumpywizard.com --&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-7404049884447783953?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=uRYJW5Dimdk:mkVfGc2muCo:Osvv7CGXBvU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=Osvv7CGXBvU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=uRYJW5Dimdk:mkVfGc2muCo:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/uRYJW5Dimdk" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/7404049884447783953?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/7404049884447783953?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2011/10/tweetflection-point.html" title="Tweetflection Point" /><author><name>Denton Gentry</name><uri>https://profiles.google.com/103797409565331693058</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-tdZM5hM_1D0/AAAAAAAAAAI/AAAAAAAAClE/SIaTjGU1fTQ/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-v2eTchTOCBk/Tqqm7inE2TI/AAAAAAAADLU/irznL-P6kNY/s72-c/datapoints.png" height="72" width="72" /></entry><entry gd:etag="W/&quot;C0UFQ3k7eSp7ImA9WhdaFEs.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-8512291114894506343</id><published>2011-10-24T06:00:00.000-07:00</published><updated>2011-10-24T06:00:12.701-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-24T06:00:12.701-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Ethernet" /><title>Well Trodden Technology Paths</title><content type="html">&lt;p&gt;Modern CPUs are astonishingly complex, with huge numbers of caches, lookaside buffers, and other features to optimize performance. Hardware reset is generally insufficient to initialize these features for use: reset leaves them in a known state, but not a useful one. Extensive software initialization is required to get all of the subsystems working.&lt;/p&gt;

&lt;p&gt;Its quite difficult to design such a complex CPU to handle its own initialization out of reset. The hardware verification wants to focus on the &amp;quot;normal&amp;quot; mode of operation, with all hardware functions active, but handling the boot case requires that a vast number of partially initialized CPU configurations also be verified. Any glitch in these partially initialized states results in a CPU which cannot boot, and is therefore useless.&lt;/p&gt;

&lt;img border="0" width="224" height="186" align="right" src="http://1.bp.blogspot.com/-hwgWeVKC1dM/TqRxQAkmo3I/AAAAAAAADHI/PUb0A0TpmSw/s320/montalvo.png" style="border: none; margin: 0;" alt="Large CPU with many cores, and a small 68k CPU in the corner." title="Can you run Hypercard on that thing?"&gt;

&lt;p&gt;Many, and I'd hazard to guess &lt;i&gt;most,&lt;/i&gt; complex CPU designs reduce their verification cost and design risk by relying on a far simpler CPU buried within the system to handle the earliest stages of initialization. For example, the &lt;a href="http://en.wikipedia.org/wiki/Montalvo_Systems"&gt;Montalvo x86 CPU&lt;/a&gt; design contained a small 68000 core to handle many tasks of getting it running. The 68k was an existing, well proven logic design requiring minimal verification by the ASIC team. That small CPU went through the steps to initialize all the various hardware units of the larger CPUs around it before releasing them from reset. It ran an image fetched from flash which could be updated with new code as needed.&lt;/p&gt;

&lt;br/&gt;&amp;nbsp;&lt;br/&gt;
&lt;h3&gt;Warning: Sudden Segue Ahead&lt;/h3&gt;
&lt;p&gt;Networking today is at the cusp of a transition, one which other parts of the computing market have already undergone. We're quickly shifting from fixed-function switch fabrics to software defined networks. This shift bears remarkable similarities to the graphics industry shifting from fixed 3D pipelines to GPUs, and of CPUs shedding their coprocessors to focus on delivering more general purpose computing power.&lt;/p&gt;

&lt;p&gt;Networking will also face some of the same issues as modern CPUs, where the optimal design for performance in normal operation is not suitable for handling its own control and maintenance. Last week's &lt;a href="http://codingrelic.geekhold.com/2011/10/layer-2-history.html"&gt;ruminations about L2 learning&lt;/a&gt; are one example: though we can make a case for software provisioning of MAC addresses, the result is a network which doesn't handle topology changes without software stepping in to reprovision.&lt;/p&gt;

&lt;p&gt;The control network cannot, itself, seize up whenever there is a problem. The control network has to be robust in handling link failures and topology changes, to allow software to reconfigure the rest of the data-carrying network. This could mean an out of band control network, hooked to the ubiquitous Management ports on enterprise and datacenter switches. It might also be that a VLAN used for control operates in a very different fashion than one used for data, learning L2 addresses dynamically and using MSTP to handle link failures.&lt;/p&gt;

&lt;p&gt;All in all, its an exciting time to be in networking.&lt;/p&gt;

&lt;br/&gt;

&lt;!-- mjha1667@frumpywizard.com --&gt;
&lt;!-- yitzashim1667 AT frumpywizard.com --&gt;
&lt;!-- magen1667 AT frumpywizard DOT com --&gt;
&lt;!-- tarussov1667 AT GMail --&gt;
&lt;!-- palshi1667.REMOVENOSPAM@frumpywizard.com --&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-8512291114894506343?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=GZbABVDHJGA:rFqamDuEtFY:Osvv7CGXBvU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=Osvv7CGXBvU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=GZbABVDHJGA:rFqamDuEtFY:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/GZbABVDHJGA" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/8512291114894506343?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/8512291114894506343?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2011/10/well-trodden-technology-paths.html" title="Well Trodden Technology Paths" /><author><name>Denton Gentry</name><uri>https://profiles.google.com/103797409565331693058</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-tdZM5hM_1D0/AAAAAAAAAAI/AAAAAAAAClE/SIaTjGU1fTQ/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-hwgWeVKC1dM/TqRxQAkmo3I/AAAAAAAADHI/PUb0A0TpmSw/s72-c/montalvo.png" height="72" width="72" /></entry><entry gd:etag="W/&quot;CEcDQXo5fSp7ImA9WhdaFE0.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-1120682562158233769</id><published>2011-10-23T13:34:00.000-07:00</published><updated>2011-10-23T13:34:30.425-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-23T13:34:30.425-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Python" /><title>Tornado HTTPClient Chunked Downloads</title><content type="html">&lt;p&gt;&lt;a href="http://www.tornadoweb.org/"&gt;Tornado&lt;/a&gt; is an open source web server in Python. It was originally developed to power &lt;a href="http://friendfeed.com/"&gt;friendfeed.com&lt;/a&gt;, and excels at non-blocking operations for real-time web services.&lt;/p&gt;

&lt;p&gt;Tornado includes an HTTP client as well, to fetch files from other servers. I found a number of examples of how to use it, but all of them would fetch the entire item and return it in a callback. I plan to fetch some rather large multi-megabyte files, and don't see a reason to hold them entirely in memory. Here is an example of how to get partial updates as the download progresses: pass in a streaming_callback to the HTTPRequest().&lt;/p&gt;

&lt;p&gt;The streaming_callback will be called for each chunk of data from the server. 4 KBytes is a common chunk size. The async_callback will be called when the file has been fully fetched; the response.data will be empty&lt;/p&gt;

&lt;pre style="font-family: monospace; font-size: small; line-height: 1.3em; margin-left: 3em;"&gt;#!/usr/bin/python

import os
import tempfile
import tornado.httpclient
import tornado.ioloop

class HttpDownload(object):
  def __init__(self, url, ioloop):
    self.ioloop = ioloop
    self.tempfile = tempfile.NamedTemporaryFile(delete=False)
    req = tornado.httpclient.HTTPRequest(
        url = url,
        &lt;b&gt;streaming_callback = self.streaming_callback&lt;/b&gt;)
    http_client = tornado.httpclient.AsyncHTTPClient()
    http_client.fetch(req, self.async_callback)

  &lt;b&gt;def streaming_callback(self, data):
    self.tempfile.write(data)&lt;/b&gt;

  def async_callback(self, response):
    self.tempfile.flush()
    self.tempfile.close()
    if response.error:
      print "Failed"
      os.unlink(self.tempfile.name)
    else:
      print("Success: %s" % self.tempfile.name)
      self.ioloop.stop()

def main():
  ioloop = tornado.ioloop.IOLoop.instance()
  dl = HttpDownload("http://codingrelic.geekhold.com/", ioloop)
  ioloop.start()

if __name__ == '__main__':
  main()
&lt;/pre&gt;

&lt;p&gt;I'm mostly blogging this for my own future use, to be able to find how to do something I remember doing before. There you go, future me.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-1120682562158233769?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=9E5ipKQY9JY:kiYLT_ngUPc:Osvv7CGXBvU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=Osvv7CGXBvU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=9E5ipKQY9JY:kiYLT_ngUPc:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/9E5ipKQY9JY" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/1120682562158233769?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/1120682562158233769?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2011/10/tornado-httpclient-chunked-downloads.html" title="Tornado HTTPClient Chunked Downloads" /><author><name>Denton Gentry</name><uri>https://profiles.google.com/103797409565331693058</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-tdZM5hM_1D0/AAAAAAAAAAI/AAAAAAAAClE/SIaTjGU1fTQ/s512-c/photo.jpg" /></author></entry><entry gd:etag="W/&quot;A0UEQnwyfip7ImA9WhdaEE8.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-789551907277275712</id><published>2011-10-19T06:00:00.000-07:00</published><updated>2011-10-19T06:00:03.296-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-19T06:00:03.296-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Ethernet" /><title>Layer 2 History</title><content type="html">&lt;p&gt;&lt;span style="font-weight: bold;"&gt;Why use L2 networks in datacenters?&lt;/span&gt;&lt;br/&gt;
Virtual machines need to move from one physical server to another, to balance load. To avoid disrupting service, their IP address cannot change as a result of this move. That means the servers need to be in the same L3 subnet, leading to enormous L2 networks.&lt;/p&gt;

&lt;p&gt;&lt;span style="font-weight: bold;"&gt;Why are enormous L2 networks a problem?&lt;/span&gt;&lt;br/&gt;
A switch looks up the destination MAC address of the packet it is forwarding. If the switch knows what port that MAC address is on, it sends the packet to that port. If the switch does not know where the MAC address is, it floods the packet to &lt;i&gt;all&lt;/i&gt; ports. The amount of flooding traffic tends to rise as the number of stations attached to the L2 network increases.&lt;/p&gt;

&lt;img border="0" width="227" height="173" align="right" src="http://3.bp.blogspot.com/-zfdYvE-7ryM/Tpssrf-sG3I/AAAAAAAADAo/aPvGYWBRzG0/s320/Transition.png" style="border: none; margin: 0;" alt="Transition from half duplexed Ethernet to L2 switching." title="I miss vampire taps."&gt;

&lt;p&gt;&lt;span style="font-weight: bold;"&gt;Why do L2 switches flood unknown address packets?&lt;/span&gt;&lt;br/&gt;
So they can learn where that address is. Flooding the packet to all ports means that if that destination exists, it should see the packet and respond. The source address in the response packet lets the switches learn where that address is.&lt;/p&gt;

&lt;p&gt;&lt;span style="font-weight: bold;"&gt;Why do L2 switches need to learn addresses dynamically?&lt;/span&gt;&lt;br/&gt;
Because they replaced simpler repeaters (often called hubs). Repeaters required no configuration, they just repeated the packet they saw on one segment to all other segments. Requiring extensive configuration of MAC addresses for switches would have been an enormous drawback.&lt;/p&gt;

&lt;p&gt;&lt;span style="font-weight: bold;"&gt;Why did repeaters send packets to all segments?&lt;/span&gt;&lt;br/&gt;
Repeaters were developed to scale up Ethernet networks. Ethernet at that time mostly used coaxial cable. Once attached to the cable, the station could see all packets from all other stations. Repeaters kept that same property.&lt;/p&gt;

&lt;p&gt;&lt;span style="font-weight: bold;"&gt;How could all stations see all packets?&lt;/span&gt;&lt;br/&gt;
There were &lt;a href="http://codingrelic.geekhold.com/2011/04/discrimination-on-basis-of-bytes.html"&gt;limits placed&lt;/a&gt; on the maximum cable length, propagation delay through a repeater, and the number of repeaters in an Ethernet network. The speed of light in the coaxial cable used for the original Ethernet networks is 0.77c, or 77% of the speed of light in a vacuum. Ethernet has a minimum packet size to allow sufficient time for the first bit of the packet to propagate all the way across the topology and back before the packet ends transmission.&lt;/p&gt;

&lt;p&gt;So there you go. We build datacenter networks this way because of the speed of light in coaxial cable.&lt;/p&gt;

&lt;br/&gt;

&lt;!-- mjha1667@frumpywizard.com --&gt;
&lt;!-- yitzashim1667 AT frumpywizard.com --&gt;
&lt;!-- magen1667 AT frumpywizard DOT com --&gt;
&lt;!-- tarussov1667 AT GMail --&gt;
&lt;!-- palshi1667.REMOVENOSPAM@frumpywizard.com --&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-789551907277275712?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=H8GeRUDgfyk:-pSHHcuPpsY:Osvv7CGXBvU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=Osvv7CGXBvU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=H8GeRUDgfyk:-pSHHcuPpsY:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/H8GeRUDgfyk" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/789551907277275712?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/789551907277275712?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2011/10/layer-2-history.html" title="Layer 2 History" /><author><name>Denton Gentry</name><uri>https://profiles.google.com/103797409565331693058</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-tdZM5hM_1D0/AAAAAAAAAAI/AAAAAAAAClE/SIaTjGU1fTQ/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-zfdYvE-7ryM/Tpssrf-sG3I/AAAAAAAADAo/aPvGYWBRzG0/s72-c/Transition.png" height="72" width="72" /></entry><entry gd:etag="W/&quot;DUcMQ3o9fCp7ImA9WhdbGEs.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-2229171199975846874</id><published>2011-10-17T08:58:00.000-07:00</published><updated>2011-10-17T08:58:02.464-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-17T08:58:02.464-07:00</app:edited><title>Complexity All the Way Down</title><content type="html">&lt;p&gt;&lt;a href="https://plus.google.com/u/0/112218872649456413744/about"&gt;Jean-Baptiste Queru&lt;/a&gt; recently wrote a &lt;a href="https://plus.google.com/u/0/112218872649456413744/posts/dfydM2Cnepe"&gt;brilliant essay titled &lt;i&gt;Dizzying but invisible depth,&lt;/i&gt;&lt;/a&gt; a description of the sheer, unimaginable complexity at each layer of modern computing infrastructure. It is worth a read.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-2229171199975846874?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=ZQ_WgknqiO8:LfycanPf6wg:Osvv7CGXBvU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=Osvv7CGXBvU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=ZQ_WgknqiO8:LfycanPf6wg:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/ZQ_WgknqiO8" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/2229171199975846874?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/2229171199975846874?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2011/10/complexity-all-way-down.html" title="Complexity All the Way Down" /><author><name>Denton Gentry</name><uri>https://profiles.google.com/103797409565331693058</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-tdZM5hM_1D0/AAAAAAAAAAI/AAAAAAAAClE/SIaTjGU1fTQ/s512-c/photo.jpg" /></author></entry><entry gd:etag="W/&quot;AkUBRXc9eCp7ImA9WhdbFk4.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-2025456073183545895</id><published>2011-10-12T21:28:00.000-07:00</published><updated>2011-10-14T17:24:14.960-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-14T17:24:14.960-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Engineering Life" /><title>Dennis Ritchie, 1941-2011</title><content type="html">&lt;a href="http://en.wikipedia.org/wiki/The_C_Programming_Language"&gt;&lt;img border="0" width="226" height="298" align="right" src="http://2.bp.blogspot.com/-TarY827nbuM/TpZnhdioZ4I/AAAAAAAAC9E/gdTBAET1lu4/s320/C.jpg" style="border: none; margin: 0;" alt="Kernighan and Ritchie _The C Programming Language_" title="Image courtesy Wikipedia."&gt;&lt;/a&gt;
&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/The_C_Programming_Language"&gt;K&amp;amp;R C&lt;/a&gt; is the finest programming language book ever published. Its &lt;i&gt;terseness&lt;/i&gt; is a hallmark of the work of Dennis Ritchie; it says exactly what needs to be said, and nothing more.&lt;/p&gt;

&lt;p&gt;Rest in Peace, Dennis Ritchie.&lt;/p&gt;

&lt;p&gt;The first generation of computer pioneers are already gone. We're beginning to lose the second generation.&lt;/p&gt;

&lt;br/&gt;

&lt;!-- mjha1667@frumpywizard.com --&gt;
&lt;!-- yitzashim1667 AT frumpywizard.com --&gt;
&lt;!-- magen1667 AT frumpywizard DOT com --&gt;
&lt;!-- tarussov1667 AT GMail --&gt;
&lt;!-- palshi1667.REMOVENOSPAM@frumpywizard.com --&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-2025456073183545895?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=Z0SuOZZVkc8:hqUzI45YhVs:Osvv7CGXBvU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=Osvv7CGXBvU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=Z0SuOZZVkc8:hqUzI45YhVs:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/Z0SuOZZVkc8" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/2025456073183545895?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/2025456073183545895?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2011/10/dennis-ritchie-1941-2011.html" title="Dennis Ritchie, 1941-2011" /><author><name>Denton Gentry</name><uri>https://profiles.google.com/103797409565331693058</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-tdZM5hM_1D0/AAAAAAAAAAI/AAAAAAAAClE/SIaTjGU1fTQ/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-TarY827nbuM/TpZnhdioZ4I/AAAAAAAAC9E/gdTBAET1lu4/s72-c/C.jpg" height="72" width="72" /></entry><entry gd:etag="W/&quot;C0EESH4-fyp7ImA9WhdbEkg.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-5383031585618196980</id><published>2011-10-10T06:00:00.000-07:00</published><updated>2011-10-10T06:00:09.057-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-10T06:00:09.057-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="architecture" /><title>ld-http.so</title><content type="html">&lt;p&gt;In the last decade we have enjoyed a renaissance of programming language development. Clojure, Scala, Python, C#/F#/et al, Ruby (and Rails), Javascript, node.js, Haskell, Go, and the list goes on. Development of many of those languages started in the 1990s, but adoption accelerated in the 2000s.&lt;/p&gt;

&lt;p&gt;Why now? There are probably a lot of reasons, but I want to opine on one.&lt;/p&gt;

&lt;div style="width: 20em; text-align: center; font-style: italic; margin: auto; border: 1px #777; background-color: #eee; padding: 1em;"&gt;HTTP is our program linker.&lt;/div&gt;

&lt;!--
&lt;p&gt;Commonly used operating systems have for decades been written primarily in some variant of C. The system libraries often only had C bindings, which in turn encouraged other third party libraries to be in C in order to easily link. Programming languages which evolved in that era had to easily interface with C code, it was impractical to redevelop every facility one might want to use. The Java Native Interface was very important during the first few years of Java deployment, while Python and Tcl also had simple extension mechanisms. Java, Perl, and Python gradually developed extensive standard libraries, though even these used a lot of C code.&lt;/p&gt;
--&gt;

&lt;p&gt;We no longer have to worry about linking to a gazillion libraries written in different languages, with all of the compatibility issues that entails.  We no longer build large software systems by linking it all into ginormous binaries, and that loosens a straightjacket which made it difficult to stray too far from C. We dabbled with DCE/CORBA/SunRPC as a way to decouple systems, but RPC marshaling semantics still dragged in a bunch of assumptions about data types.&lt;/p&gt;

&lt;p&gt;It took the web and the model of software as a service running on server farms to really decompose large systems into cooperating subsystems which could be implemented any way they like. Facebook can implement &lt;a href="http://www.facebook.com/note.php?note_id=14218138919"&gt;chat in Erlang&lt;/a&gt;, Akamai can use Clojure, Google can mix C++ with Java/Python/Go/etc. It is all connected together via HTTP, sometimes carrying SOAP or other RPCs, and sometimes with RESTful interfaces even inside the system.&lt;/p&gt;

&lt;br/&gt;

&lt;!-- mjha1667@frumpywizard.com --&gt;
&lt;!-- yitzashim1667 AT frumpywizard.com --&gt;
&lt;!-- magen1667 AT frumpywizard DOT com --&gt;
&lt;!-- tarussov1667 AT GMail --&gt;
&lt;!-- palshi1667.REMOVENOSPAM@frumpywizard.com --&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-5383031585618196980?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=6YYiWYRYPQ4:0ANvRS0k6rc:Osvv7CGXBvU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=Osvv7CGXBvU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=6YYiWYRYPQ4:0ANvRS0k6rc:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/6YYiWYRYPQ4" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/5383031585618196980?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/5383031585618196980?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2011/10/ld-httpso.html" title="ld-http.so" /><author><name>Denton Gentry</name><uri>https://profiles.google.com/103797409565331693058</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-tdZM5hM_1D0/AAAAAAAAAAI/AAAAAAAAClE/SIaTjGU1fTQ/s512-c/photo.jpg" /></author></entry><entry gd:etag="W/&quot;DUUNQ3c7eip7ImA9WhdbEE8.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-3825532665247078223</id><published>2011-10-07T06:02:00.000-07:00</published><updated>2011-10-07T15:41:32.902-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-07T15:41:32.902-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Engineering Life" /><title>Finding Ada, 2011</title><content type="html">&lt;div style="width: 80%; font-style: italic; margin: auto;"&gt;Ada Lovelace Day aims to raise the profile of women in science, technology, engineering and maths by encouraging people around the world to talk about the women whose work they admire. This international day of celebration helps people learn about the achievements of women in STEM, inspiring others and creating new role models for young and old alike.&lt;div style="text-align: right; color: #bbb; font-size: 80%;"&gt;&lt;a href="http://findingada.com/about-finding-ada/"&gt;findingada.com&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;

&lt;br/&gt;
&lt;p&gt;For Ada Lovelace Day 2010 I analyzed a patent for a &lt;a href="http://codingrelic.geekhold.com/2010/03/player-piano-torpedoes.html"&gt;frequency hopping control system for guided torpedoes&lt;/a&gt;, granted to &lt;a href="http://en.wikipedia.org/wiki/Hedy_Lamarr"&gt;Hedy Lamarr&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/George_Antheil"&gt;George Antheil&lt;/a&gt;. For Ada Lovelace Day this year I want to share a story from early in my career.&lt;/p&gt;

&lt;p&gt;After graduation I worked on ASICs for a few years, mostly on Asynchronous Transfer Mode NICs for Sun workstations. In the 1990s Sun made large investments in ATM: designed its own Segmentation and Reassembly ASICs, wrote a q.2931 signaling stack, adapted NetSNMP as an ILMI stack, wrote Lan Emulation and MPOA implementations, etc.&lt;/p&gt;

&lt;p&gt;Yet ATM wasn't a great fit for carrying data traffic. Its overhead for cell headers was very high, it had an unnatural fondness for Sonet as its physical layer, and it required a signaling protocol far more complex than the simple ARP protocol of Ethernet.&lt;/p&gt;

&lt;p&gt;&lt;img border="0" width="320" height="126" align="right" src="http://4.bp.blogspot.com/-ERIArdBaZ2s/To6FbVkiiBI/AAAAAAAAC5k/o1Jaw_yqU3U/s1600/aal5.png" style="border: none; margin: 0;" alt="Cell loss == packet loss." title="Theres a hole in my packet, dear Liza, dear Liza, theres a hole in my packet, dear Liza, a hole."&gt;Its most pernicious problem for data networking was in dealing with congestion. There was no mechanism for flow control, because ATM evolved out of a circuit switched world with predictable traffic patterns. Congestive problems come when you try to switch packets and deal with bursty traffic. In an ATM network the loss of a single cell would render the entire packet unusable, but the network would be further congested carrying the remaining cells of that packet's corpse.&lt;/p&gt;

&lt;p&gt;Allyn Romanow at Sun Microsystems and &lt;a href="http://icir.org/floyd/"&gt;Sally Floyd&lt;/a&gt; from the Lawrence Berkeley Labs conducted a series of simulations, ultimately &lt;a href="ftp://ftp.ee.lbl.gov/papers/tcp_atm.ps.Z"&gt;resulting in a paper&lt;/a&gt; on how to deal with congestion. If a cell had to be dropped, drop the rest of the cells in that packet. Furthermore, deliberately &lt;a href="http://codingrelic.geekhold.com/2011/03/random-early-mea-culpa.html"&gt;dropping packets early&lt;/a&gt; as buffering approached capacity was even better, and brought ATM links up to the same efficiency for TCP transport as native packet links. Allyn was very generous with her time in explaining the issues and how to solve them, both in ATM congestion control and in a number of other aspects of making a network stable.&lt;/p&gt;

&lt;p&gt;ATM also had a very complex signaling stack for setting up connections, so complex that many ATM deployments simply gave up and permanently configured circuits everywhere they needed to go. PVCs only work up to a point, the network size is constrained by the number of available circuits. Renee Danson Sommerfeld took on the task of writing a q.2931 signaling stack for Solaris, requiring painstaking care with specifications and interoperability testing. Sun's ATM products were never reliant on PVCs to operate, they could set up switched circuits on demand and close them when no longer needed.&lt;/p&gt;

&lt;p&gt;In this industry we tend to celebrate engineers who spend massive effort putting out fires. What I learned from Allyn, Sally, and Renee is that the truly &lt;i&gt;great&lt;/i&gt; engineers see the fire coming, and keep it from spreading in the first place.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Update:&lt;/b&gt; &lt;a href="http://www.kebe.com/~danmcd/"&gt;Dan McDonald&lt;/a&gt; worked at Sun in the same timeframe, and &lt;a href="http://kebesays.blogspot.com/2011/10/finding-ada-but-with-better-technology.html"&gt;posted his own recollections&lt;/a&gt; of working with Allyn, Sally, and Renee. As &lt;a href="https://plus.google.com/103797409565331693058/posts/AiuqrLgD5Xz"&gt;he put it on Google+&lt;/a&gt;, &amp;quot;Good choices for people, poor choice for technology.&amp;quot; &lt;i&gt;(i.e. ATM Considered Harmful).&lt;/i&gt;&lt;/p&gt;

&lt;br/&gt;

&lt;!-- mjha1667@frumpywizard.com --&gt;
&lt;!-- yitzashim1667 AT frumpywizard.com --&gt;
&lt;!-- magen1667 AT frumpywizard DOT com --&gt;
&lt;!-- tarussov1667 AT GMail --&gt;
&lt;!-- palshi1667.REMOVENOSPAM@frumpywizard.com --&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-3825532665247078223?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=6dnwsGl0bCs:C2i1uqB-Ph0:Osvv7CGXBvU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=Osvv7CGXBvU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=6dnwsGl0bCs:C2i1uqB-Ph0:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/6dnwsGl0bCs" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/3825532665247078223?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/3825532665247078223?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2011/10/finding-ada-2011.html" title="Finding Ada, 2011" /><author><name>Denton Gentry</name><uri>https://profiles.google.com/103797409565331693058</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-tdZM5hM_1D0/AAAAAAAAAAI/AAAAAAAAClE/SIaTjGU1fTQ/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-ERIArdBaZ2s/To6FbVkiiBI/AAAAAAAAC5k/o1Jaw_yqU3U/s72-c/aal5.png" height="72" width="72" /></entry><entry gd:etag="W/&quot;A0ECQX49eip7ImA9WhdUGEw.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-5873850301735480068</id><published>2011-10-05T06:01:00.000-07:00</published><updated>2011-10-05T06:01:00.062-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-05T06:01:00.062-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Ethernet" /><title>Non Uniform Network Access</title><content type="html">&lt;p&gt;&lt;img border="0" width="212" height="178" align="right" src="http://2.bp.blogspot.com/-bqQ-jM2gURk/TovldW9_ypI/AAAAAAAAC5M/4DZ5VTL4bDA/s320/numa.png" style="border: none; margin: 0;" alt="Four CPUs in a ring, with RAM attached to each." title="Confession: I find cache coherency overrated."&gt;&lt;a href="http://en.wikipedia.org/wiki/Non-Uniform_Memory_Access"&gt;Non Uniform Memory Access&lt;/a&gt; is common in modern x86 servers. RAM is connected to each CPU, which connect to each other. Any CPU can access any location in RAM, but will incur additional latency if there are multiple hops along the way. This is the &lt;i&gt;non-uniform&lt;/i&gt; part: some portions of memory take longer to access than others.&lt;/p&gt;

&lt;p&gt;Yet the NUMA we use today is NUMA &lt;span style="font-size: 90%;"&gt;in&lt;/span&gt; &lt;span style="font-size: 80%;"&gt;the&lt;/span&gt; &lt;span style="font-size: 70%;"&gt;small&lt;/span&gt;. In the 1990s NUMA aimed to make very, very large systems commonplace. There were many levels of bridging, each adding yet more latency. RAM attached to the local CPU was fast, RAM for other CPUs on the same board was somewhat slower. RAM on boards in the same local grouping took longer still, while RAM on the other side of the chassis took forever. Nonetheless this was considered to be a huge advancement in system design because it allowed the software to access vast amounts of memory in the system with a uniform programming interface... &lt;b&gt;except for performance.&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Operating system schedulers which had previously run any task on any available CPU would randomly exhibit extremely bad behavior: a process running on distant combinations of CPU and RAM would run an order of magnitude slower. NUMA meant that all RAM was equal, but some was more equal than others. Operating systems desperately added notions of RAM affinity to go along with CPU and cache affinity, but reliably good performance was difficult to achieve.&lt;/p&gt;

&lt;p&gt;As an industry we concluded that NUMA in moderation is good, but too much NUMA is bad. Those enormous NUMA systems have mostly lost out to smaller servers clustered together, where each server uses a bit of NUMA to improve its own scalability. The big jump in latency to get to another server is accompanied by a change in API, to use the network instead of memory pointers.&lt;/p&gt;


&lt;br/&gt;&amp;nbsp;&lt;br/&gt;
&lt;h3&gt;A Segue to Web Applications&lt;/h3&gt;
&lt;!--
&lt;p&gt;The common conception of a web application is multiple front end servers running PHP/Rails/etc, all communicating with a backend MySQL/Postgres/etc database. Though a vast number of sites do work that way, web applications have rapidly accumukated far more moving parts. Large web apps consist of cooperating processes, sometimes co-resident on a single system and sometimes distributed, but communicating by IP and web protocols in either case. This reliance on networked protocols has made possible a renaissance in programming languages: linking them together is now done using HTTP and not via an ELF toolchain. Components of the web application can be implemented in Ruby, Python, Clojure, Scala, Erlang, node.js, etc, whatever is most appropriate for that specific piece, with HTTP plumbing them together.&lt;/p&gt;
--&gt;

&lt;img border="0" width="307" height="222" align="right" src="http://3.bp.blogspot.com/-CDOpUyoz8Ls/TovlkzF2knI/AAAAAAAAC5U/5Vk-bGkF2Is/s320/dc_knobs.jpg" style="border: none; margin: 0;" alt="Tuning knobs for CPU, Memory, Network." title="There are little knobs on the wall of every datacenter. I have photographic proof."&gt;
&lt;p&gt;Modern web applications can make tradeoffs between CPU utilization, memory footprint, and network bandwidth. Increase the amount of memory available for caching, and reduce the CPU required to recalculate results. Shard the data across more nodes to reduce the memory footprint on each at the cost of increasing network bandwidth. In many cases these tradeoffs don't need to be baked deep in the application, they can be tweaked via relatively simple changes. They can be adjusted to tune the application for RAM size, or for the availability of network bandwidth.&lt;/p&gt;


&lt;br/&gt;&amp;nbsp;&lt;br/&gt;
&lt;h3&gt;Further Segue To Overlay Networks&lt;/h3&gt;
&lt;p&gt;There is a lot of effort being put &lt;a href="http://codingrelic.geekhold.com/2011/09/care-and-feeding-of-vxlan.html"&gt;into overlay networks&lt;/a&gt; &lt;a href="http://codingrelic.geekhold.com/2011/10/nvgre-musings.html"&gt;for virtualized datacenters&lt;/a&gt;, to create an L2 network atop an L3 infrastructure. This allows the infrastructure to run as an L3 network, which we are pretty good at scaling and managing, while the service provided to the VMs behaves as an L2 network.&lt;/p&gt;

&lt;p&gt;Yet once the packets are carried in IP tunnels they can, through the magic of routing, be carried across a WAN to another facility. The datacenter network can be transparently extended to include resources in several locations. Transparently, &lt;b&gt;except for performance.&lt;/b&gt; The round trip time across a WAN will inevitably be longer than the LAN, the speed of light demands it. Even for geographically close facilities the bandwidth available over a WAN will be far less than the bandwidth available within a datacenter, perhaps orders of magnitude less. Application tuning parameters set based on the performance within a single datacenter will be horribly wrong across the WAN.&lt;/p&gt;

&lt;p&gt;I've no doubt that people will do it anyway. We will see L2 overlay networks being carried across VPNs to link datacenters together transparently (except for performance). Like the OS schedulers suddenly finding themselves in a NUMA world, software infrastructure within the datacenter will find itself in a network where some links are more equal than others. As an industry, we'll spend a couple years figuring out whether that was a good idea or not.&lt;/p&gt;

&lt;br/&gt;
&lt;p style="font-size: 90%; color: #777; font-style: italic;"&gt;footnote: this blog contains articles on a range of topics. If you want more posts like this, I suggest the &lt;a href="http://codingrelic.geekhold.com/search/label/Ethernet"&gt;Ethernet&lt;/a&gt; label.&lt;/p&gt;

&lt;!-- mjha1667@frumpywizard.com --&gt;
&lt;!-- yitzashim1667 AT frumpywizard.com --&gt;
&lt;!-- magen1667 AT frumpywizard DOT com --&gt;
&lt;!-- tarussov1667 AT GMail --&gt;
&lt;!-- palshi1667.REMOVENOSPAM@frumpywizard.com --&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-5873850301735480068?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=8Np7TuZUgec:WjyPWXZkWRU:Osvv7CGXBvU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=Osvv7CGXBvU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=8Np7TuZUgec:WjyPWXZkWRU:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/8Np7TuZUgec" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/5873850301735480068?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/5873850301735480068?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2011/10/non-uniform-network-access.html" title="Non Uniform Network Access" /><author><name>Denton Gentry</name><uri>https://profiles.google.com/103797409565331693058</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-tdZM5hM_1D0/AAAAAAAAAAI/AAAAAAAAClE/SIaTjGU1fTQ/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-bqQ-jM2gURk/TovldW9_ypI/AAAAAAAAC5M/4DZ5VTL4bDA/s72-c/numa.png" height="72" width="72" /></entry><entry gd:etag="W/&quot;DEYGRXo-eip7ImA9WhdUFUo.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-8342080655519665208</id><published>2011-10-02T10:22:00.000-07:00</published><updated>2011-10-02T10:22:04.452-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-02T10:22:04.452-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Ethernet" /><title>NVGRE Musings</title><content type="html">&lt;p&gt;It is an interesting time to be involved in datacenter networking. There have been announcements recently of two competing proposals for running virtual L2 networks as an overlay atop a underlying IP network, &lt;a href="http://tools.ietf.org/html/draft-mahalingam-dutt-dcops-vxlan-00"&gt;VXLAN&lt;/a&gt; and &lt;a href="http://tools.ietf.org/html/draft-sridharan-virtualization-nvgre-00"&gt;NVGRE.&lt;/a&gt; Supporting an L2 service is important for virtualized servers, which need to be able to move from one physical server to another without changing their IP address or interrupting the services they provide. Having written about VXLAN in a &lt;a href="http://codingrelic.geekhold.com/2011/09/care-and-feeding-of-vxlan.html"&gt;series&lt;/a&gt; of &lt;a href="http://codingrelic.geekhold.com/2011/09/vxlan-part-deux.html"&gt;three&lt;/a&gt; &lt;a href="http://codingrelic.geekhold.com/2011/09/vxlan-conclusion.html"&gt;posts,&lt;/a&gt; now it is time for NVGRE. &lt;a href="https://twitter.com/#!/ioshints"&gt;Ivan Pepelnjak&lt;/a&gt; has already posted about it on &lt;a href="http://blog.ioshints.info/2011/09/nvgre-because-one-standard-just-wouldnt.html"&gt;IOShints&lt;/a&gt;, which I recommend reading.&lt;/p&gt;

&lt;p&gt;NVGRE encapsulates L2 frames inside tunnels to carry them across an L3 network. As its name implies, it uses &lt;a href="http://en.wikipedia.org/wiki/Generic_Routing_Encapsulation"&gt;GRE tunneling&lt;/a&gt;. GRE has been around for a very long time, and is well supported by networking gear and analysis tools. An NVGRE Endpoint uses the Key field in the GRE header to hold the Tenant Network Identifier (TNI), a 24 bit space of virtual LANs.&lt;/p&gt;

&lt;center&gt;&lt;img border="0" width="481" height="49" src="http://2.bp.blogspot.com/-RVgDtp7_ly4/TochoyfTLjI/AAAAAAAAC4A/X9iXbjP01Lk/s1600/headers.png" style="border: none; margin: 0;" alt="Outer MAC, Outer IP, GRE, Inner MAC, Inner Payload, Outer FCS." title="Eventually there will be enough layers of headers to classify them like DNA fingerprints, a banded chart with highlites of active versus non-coding regions."&gt;&lt;/center&gt;

&lt;p&gt;The encapsulated packet has no Inner CRC. When VMs send packets to other VMs within a server they do not calculate a CRC, one is added by a physical NIC when the packet leaves the server. As the NVGRE Endpoint is likely to be a software component within the server, prior to hitting any NIC, the frames have no CRC. This is another case where even on L2 networks, the &lt;a href="http://codingrelic.geekhold.com/2009/11/ethernet-integrity-or-lack-thereof.html"&gt;Ethernet CRC&lt;/a&gt; &lt;a href="http://codingrelic.geekhold.com/2011/06/out-of-business-before-it-happens.html"&gt;does not work&lt;/a&gt; the way our intuition would suggest.&lt;/p&gt;

&lt;p&gt;The NVGRE draft refers to IP addresses in the outer header as Provider Addresses, and the inner header as Customer Addresses. NVGRE can optionally also use an IP multicast group for each TNI to distribute L2 broadcast and multicast packets.&lt;/p&gt;



&lt;br/&gt;&amp;nbsp;&lt;br/&gt;
&lt;h3&gt;Not Quite Done&lt;/h3&gt;
&lt;p&gt;As befits its &amp;quot;draft&amp;quot; designation, a number of details in the NVGRE proposal are left to be determined in future iterations. One largish bit left unspecified is mapping of Customer Addresses to Provider. When an NVGRE Endpoint needs to send a packet to a remote VM, it must know the address of the remote NVGRE Endpoint. The mechanism to maintain this mapping is not yet defined, though it will be provisioned by a control function communicating with the Hypervisors and switches.&lt;/p&gt;



&lt;br/&gt;&amp;nbsp;&lt;br/&gt;
&lt;h3&gt;&lt;i&gt;Optional&lt;/i&gt; Multicast?&lt;/h3&gt;
&lt;p&gt;The NVGRE draft calls out broadcast and multicast support as being optional, only if the network operator chooses to support it. To operate as a virtual Ethernet network a few broadcast protocols are essential, like ARP and IPv6 ND. Presumably if broadcast is not available, the NVGRE Endpoint would respond to these requests to its local VMs.&lt;/p&gt;

&lt;p&gt;Yet I don't see how that can work in all cases. The NVGRE control plane can certainly know the Provider Address of all NVGRE Endpoints. It can know the &lt;u&gt;MAC&lt;/u&gt; address of all guest VMs within the tenant network, because the Hypervisor provides the MAC address as part of the virtual hardware platform. There are notable exceptions where guest VMs use VRRP, or make up locally administered MAC addresses, but I'll ignore those for now.&lt;/p&gt;

&lt;p&gt;I don't see how an NVGRE Endpoint can know all Customer &lt;u&gt;IP&lt;/u&gt; Addresses. One of two things would have to happen:&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;&lt;i&gt;Require&lt;/i&gt; all customer VMs to obtain their IP from the provider. Even backend systems using private, internal addresses would have to get them from the datacenter operator so that NVGRE can know where they are.&lt;/li&gt;
	&lt;li&gt;Implement a distributed learning function where NVGRE Endpoints watch for new IP addresses sent by their VMs and report them to all other Endpoints.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The current draft of NVGRE makes no mention of either such function, so we'll have to watch for future developments.&lt;/p&gt;

&lt;p&gt;The earlier VL2 network also did not require multicast and handled ARP via a network-wide directory service. Many VL2 concepts made their way into NVGRE. So far as I understand it, VL2 assigned all IP addresses to VMs and could know where they were in the network.&lt;/p&gt;



&lt;br/&gt;&amp;nbsp;&lt;br/&gt;
&lt;h3&gt;Multipathing&lt;/h3&gt;
&lt;p&gt;&lt;img border="0" width="355" height="112" align="right" src="http://2.bp.blogspot.com/-WtV_f3KS8rw/TochzgY8VlI/AAAAAAAAC4I/LTJ3czJYCiA/s1600/lacp.png" style="border: none; margin: 0;" alt="Load balancing across four links between switches." title="The datacenter is a series of tubes."&gt;An important topic for tunneling protocols is multipathing. When multiple paths are available to a destination, either LACP at L2 or ECMP at L3, the switches have to choose which link to use. It is important that packets on the same flow stay in order, as protocols like TCP use excessive reordering as an indication of congestion. Switches hash packet headers to select a link, so packets with the same headers will always choose the same link.&lt;/p&gt;

&lt;p&gt;Tunneling protocols have issues with this type of hashing: all packets in the tunnel have the same header. This limits them to a single link, and congests that one link for other traffic. Some switch chips implement extra support for common tunnels like GRE, to include the Inner header in the hash computation. NVGRE would benefit greatly from this support. Unfortunately, it is not universal amongst modern switches.&lt;/p&gt;

&lt;p&gt;&lt;img border="0" width="360" height="107" src="http://2.bp.blogspot.com/-iscWA6pKsE0/Toch9NJgE0I/AAAAAAAAC4Q/aRPJ7UW8W1Y/s1600/hashLB.png" align="left" style="border: none; margin: 0;" align="right" alt="Choosing Provider Address by hashing the Inner headers." title="YELI (Yet Another Level of Indirection)"&gt;The NVGRE draft proposes that each NVGRE Endpoint have multiple Provider Addresses. The Endpoints can choose one of several source and destination IP addresses in the encapsulating IP header, to provide variance to spread load across LACP and ECMP links. The draft says that when the Endpoint has multiple PAs, each Customer Address will be provisioned to use one of them. In practice I suspect it would be better were the NVGRE Endpoint to hash the Inner headers to choose addresses, and distribute the load for each Customer Address across all links.&lt;/p&gt;

&lt;p&gt;Using multiple IP addresses for load balancing is clever, but I can't easily predict how well it will work. The number of different flows the switches see will be relatively small. For example if each endpoint has four addresses, the total number of different header combinations between any two endpoints is sixteen. This is sixteen times better than having a single address each, but it is still not a lot. Unbalanced link utilization seems quite possible.&lt;/p&gt;



&lt;br/&gt;&amp;nbsp;&lt;br/&gt;
&lt;h3&gt;Aside: Deliberate Multipathing&lt;/h3&gt;
&lt;p&gt;&lt;img align="right" border="0" width="275" height="191" src="https://lh3.googleusercontent.com/-FSkCRP9fWOs/TohW2LN2RhI/AAAAAAAAC4U/0ZuM1efalFY/s800/multihop.png" align="left" style="border: none; margin: 0;" align="right" alt="One LACP group feeding in to the next." title="Datacenters are a maze of twisty little passages, all different."&gt;The relatively limited variance in headers leads to an obvious next step: ensure the traffic will be balanced by predicting what the switch will do, and choose Provider IP addresses to optimize and ensure it is well balanced. In networking today we tend to solve problems by making the edges smarter.&lt;/p&gt;

&lt;p&gt;The NVGRE draft says that selection of a Provider Address is provisioned to the Endpoint. Each Customer Address will be associated with exactly one Provider Address to use. I suspect that selection of Provider Addresses is expected to be done via an optimization mechanism like this, but I'm definitely speculating.&lt;/p&gt;

&lt;p&gt;I'd caution that this is harder than it sounds. Switches use the ingress port as part of the hash calculation. That is, the same packet arriving on a different ingress port will choose a different egress link within the LACP/ECMP group. To predict behavior one needs a complete wiring diagram of the network. In the rather common case where several LACP/ECMP groups are traversed along the way to a destination, the link selected by each previous switch influences the hash computation of the next.&lt;/p&gt;

&lt;!--
&lt;p&gt;VL2 dealt with multipathing using Valiant Load Balancing which (if I understand it correctly) encapsulates a packet recursively inside several tunnels in order to steer it through the network, with Anycast to pick a path. VL2 was not just an encapsulation protocol, it defined the topology of the datacenter network. NVGRE's ambitions are more modest, and it doesn't mandate particular topologies.&lt;/p&gt;
--&gt;


&lt;br/&gt;&amp;nbsp;&lt;br/&gt;
&lt;h3&gt;Misc Notes&lt;/h3&gt;
&lt;ul&gt;
	&lt;li&gt;The NVGRE draft mentions keeping an MTU state per Endpoint, to avoid fragmentation. Details will be described in future drafts. NVGRE certainly benefits from a datacenter network with a larger MTU, but will not require it.&lt;/li&gt;
	&lt;li&gt;VXLAN describes its overlay network as existing within a datacenter. NVGRE explicitly calls for spanning across wide area networks via VPNs, for example to connect a corporate datacenter to additional resources in a cloud provider. I'll have to cover this aspect in another post, this post is too long already.&lt;/li&gt;
&lt;/ul&gt;

&lt;br/&gt;&amp;nbsp;&lt;br/&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Its quite difficult to draw a conclusion about NVGRE, as so much is still unspecified. There are two relatively crucial mapping functions which have yet to be described:&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;When a VM wants to contact a remote Customer IP and sends an ARP Request, in the absence of multicast, how can the matching MAC address be known?&lt;/li&gt;
	&lt;li&gt;When the NVGRE Endpoint is handed a frame destined to a remote Customer MAC, how does it find the Provider Address of the remote Endpoint?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So we'll wait and see.&lt;/p&gt;


&lt;br/&gt;
&lt;p style="font-size: 90%; color: #777; font-style: italic;"&gt;footnote: this blog contains articles on a range of topics. If you want more posts like this, I suggest the &lt;a href="http://codingrelic.geekhold.com/search/label/Ethernet"&gt;Ethernet&lt;/a&gt; label.&lt;/p&gt;

&lt;!-- mjha1667@frumpywizard.com --&gt;
&lt;!-- yitzashim1667 AT frumpywizard.com --&gt;
&lt;!-- magen1667 AT frumpywizard DOT com --&gt;
&lt;!-- tarussov1667 AT GMail --&gt;
&lt;!-- palshi1667.REMOVENOSPAM@frumpywizard.com --&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-8342080655519665208?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=nlVdNrFMi24:rZ379z_JoIY:Osvv7CGXBvU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=Osvv7CGXBvU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=nlVdNrFMi24:rZ379z_JoIY:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/nlVdNrFMi24" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/8342080655519665208?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/8342080655519665208?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2011/10/nvgre-musings.html" title="NVGRE Musings" /><author><name>Denton Gentry</name><uri>https://profiles.google.com/103797409565331693058</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-tdZM5hM_1D0/AAAAAAAAAAI/AAAAAAAAClE/SIaTjGU1fTQ/s512-c/photo.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-RVgDtp7_ly4/TochoyfTLjI/AAAAAAAAC4A/X9iXbjP01Lk/s72-c/headers.png" height="72" width="72" /></entry><entry gd:etag="W/&quot;CEcCQXs6fSp7ImA9WhdUEEk.&quot;"><id>tag:blogger.com,1999:blog-9151880169490356401.post-6907530764927506074</id><published>2011-09-26T06:01:00.000-07:00</published><updated>2011-09-26T06:01:00.515-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-26T06:01:00.515-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Joke" /><title>Peer Review Terminology</title><content type="html">&lt;p&gt;Many companies now include peer feedback as part of the annual review process. Each employee nominates several of their colleagues to write a review of their work from the previous year. If you are new to this process, here is some terminology which may be useful.&lt;/p&gt;

&lt;table&gt;
&lt;tr style="background-color: #fff;"&gt;
&lt;td style="font-family: Times New Roman, serif; padding: 0.5em 2px 0.5em 0;"&gt;&lt;font size="+1"&gt;&lt;b&gt;peerrihelion&lt;/b&gt;&lt;/font&gt;&lt;br/&gt;&lt;i&gt;[peer-ree-heel-yun] (noun)&lt;/i&gt;&lt;/td&gt;
&lt;td&gt;The point at which 50% of requested peer reviews are complete.&lt;/td&gt;
&lt;/tr&gt;

&lt;tr style="background-color: #f7f7f7;"&gt;
&lt;td style="font-family: Times New Roman, serif; padding: 0.5em 2px 0.5em 0;"&gt;&lt;font size="+1"&gt;&lt;b&gt;peersuasion&lt;/b&gt;&lt;/font&gt;&lt;br/&gt;&lt;i&gt;[peer-swey-zhuhn] (noun)&lt;/i&gt;&lt;/td&gt;
&lt;td&gt;A particularly glowing peer review.&lt;/td&gt;
&lt;/tr&gt;

&lt;tr style="background-color: #fff;"&gt;
&lt;td style="font-family: Times New Roman, serif; padding: 0.5em 2px 0.5em 0;"&gt;&lt;font size="+1"&gt;&lt;b&gt;peerjury&lt;/b&gt;&lt;/font&gt;&lt;br/&gt;&lt;i&gt;[peer-juh-ree] (noun)&lt;/i&gt;&lt;/td&gt;
&lt;td&gt;An &lt;u&gt;astonishingly&lt;/u&gt; glowing peer review.&lt;/td&gt;
&lt;/tr&gt;

&lt;tr style="background-color: #f7f7f7;"&gt;
&lt;td style="font-family: Times New Roman, serif; padding: 0.5em 2px 0.5em 0;"&gt;&lt;font size="+1"&gt;&lt;b&gt;peerplexed&lt;/b&gt;&lt;/font&gt;&lt;br/&gt;&lt;i&gt;[peer-plekst] (adjective)&lt;/i&gt;&lt;/td&gt;
&lt;td&gt;What exactly did they work on, anyway?&lt;/td&gt;
&lt;/tr&gt;

&lt;tr style="background-color: #fff;"&gt;
&lt;td style="font-family: Times New Roman, serif; padding: 0.5em 2px 0.5em 0;"&gt;&lt;font size="+1"&gt;&lt;b&gt;peerrational&lt;/b&gt;&lt;/font&gt;&lt;br/&gt;&lt;i&gt;[peer-rash-uh-nl] (adjective)&lt;/i&gt;&lt;/td&gt;
&lt;td&gt;Why am I reviewing this person?&lt;/td&gt;
&lt;/tr&gt;

&lt;tr style="background-color: #f7f7f7;"&gt;
&lt;td style="font-family: Times New Roman, serif; padding: 0.5em 2px 0.5em 0;"&gt;&lt;font size="+1"&gt;&lt;b&gt;peergatory&lt;/b&gt;&lt;/font&gt;&lt;br/&gt;&lt;i&gt;[peer-guh-tohr-ee] (noun)&lt;/i&gt;&lt;/td&gt;
&lt;td&gt;The set of peer reviews which may have to be declined due to lack of time.&lt;/td&gt;
&lt;/tr&gt;

&lt;tr style="background-color: #fff;"&gt;
&lt;td style="font-family: Times New Roman, serif; padding: 0.5em 2px 0.5em 0;"&gt;&lt;font size="+1"&gt;&lt;b&gt;peerfectionist&lt;/b&gt;&lt;/font&gt;&lt;br/&gt;&lt;i&gt;[peer-fek-shuh-nist] (noun)&lt;/i&gt;&lt;/td&gt;
&lt;td&gt;I spent a long time obsessing over wording.&lt;/td&gt;
&lt;/tr&gt;

&lt;tr style="background-color: #f7f7f7;"&gt;
&lt;td style="font-family: Times New Roman, serif; padding: 0.5em 2px 0.5em 0;"&gt;&lt;font size="+1"&gt;&lt;b&gt;peeriodic&lt;/b&gt;&lt;/font&gt;&lt;br/&gt;&lt;i&gt;[peer-ee-od-ik] (adjective)&lt;/i&gt;&lt;/td&gt;
&lt;td&gt;Maybe I'll just copy some of what I wrote last year.&lt;/td&gt;
&lt;/tr&gt;

&lt;tr style="background-color: #fff;"&gt;
&lt;td style="font-family: Times New Roman, serif; padding: 0.5em 2px 0.5em 0;"&gt;&lt;font size="+1"&gt;&lt;b&gt;peerritation&lt;/b&gt;&lt;/font&gt;&lt;br/&gt;&lt;i&gt;[peer-ree-tay-shun] (noun)&lt;/i&gt;&lt;/td&gt;
&lt;td&gt;Unreasonable hostility felt toward the subject of the last peer review left to be written.
&lt;/tr&gt;

&lt;tr style="background-color: #f7f7f7;"&gt;
&lt;td style="font-family: Times New Roman, serif; padding: 0.5em 2px 0.5em 0;"&gt;&lt;font size="+1"&gt;&lt;b&gt;peersecute&lt;/b&gt;&lt;/font&gt;&lt;br/&gt;&lt;i&gt;[peer-seh-kyoot] (verb)&lt;/i&gt;&lt;/td&gt;
&lt;td&gt;How nice, everyone asked for my review.&lt;/td&gt;
&lt;/tr&gt;

&lt;tr style="background-color: #fff;"&gt;
&lt;td style="font-family: Times New Roman, serif; padding: 0.5em 2px 0.5em 0;"&gt;&lt;font size="+1"&gt;&lt;b&gt;peersona non grata&lt;/b&gt;&lt;/font&gt;&lt;br/&gt;&lt;i&gt;[peer-soh-nah nohn grah-tah] (noun)&lt;/i&gt;&lt;/td&gt;
&lt;td&gt;&lt;i&gt;Nobody&lt;/i&gt; asked for my review?&lt;/td&gt;
&lt;/tr&gt;

&lt;tr style="background-color: #f7f7f7;"&gt;
&lt;td style="font-family: Times New Roman, serif; padding: 0.5em 2px 0.5em 0;"&gt;&lt;font size="+1"&gt;&lt;b&gt;peeregular&lt;/b&gt;&lt;/font&gt;&lt;br/&gt;&lt;i&gt;[peer-reg-gyu-ler] (adjective)&lt;/i&gt;&lt;/td&gt;
&lt;td&gt;An incomplete peer review, submitted anyway, just before the deadline.&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;br/&gt;

&lt;!-- mjha1667@frumpywizard.com --&gt;
&lt;!-- yitzashim1667 AT frumpywizard.com --&gt;
&lt;!-- magen1667 AT frumpywizard DOT com --&gt;
&lt;!-- tarussov1667 AT GMail --&gt;
&lt;!-- palshi1667.REMOVENOSPAM@frumpywizard.com --&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9151880169490356401-6907530764927506074?l=codingrelic.geekhold.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=ieB4_-cCHpY:j5c0Lx-5CeI:Osvv7CGXBvU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=Osvv7CGXBvU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.geekhold.com/~ff/CodingRelic?a=ieB4_-cCHpY:j5c0Lx-5CeI:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/CodingRelic?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/CodingRelic/~4/ieB4_-cCHpY" height="1" width="1"/&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/6907530764927506074?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/9151880169490356401/posts/default/6907530764927506074?v=2" /><link rel="alternate" type="text/html" href="http://codingrelic.geekhold.com/2011/09/peer-review-terminology.html" title="Peer Review Terminology" /><author><name>Denton Gentry</name><uri>https://profiles.google.com/103797409565331693058</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="//lh5.googleusercontent.com/-tdZM5hM_1D0/AAAAAAAAAAI/AAAAAAAAClE/SIaTjGU1fTQ/s512-c/photo.jpg" /></author></entry></feed>

