Added a fillmeup syscall
authorKevin Klues <klueska@ros-dev.(none)>
Sun, 25 Apr 2010 10:03:06 +0000 (03:03 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:35:44 +0000 (17:35 -0700)
This syscall is used for setting up data structures in the kernel that
allow it to stream pcaketized files directly into its memory space.
Designed for helping us specifically with our measurements for our OSDI
paper.  Will be removed at some point in the future.

14 files changed:
kern/arch/i686/ne2k.c
kern/arch/i686/nic_common.c
kern/arch/i686/nic_common.h
kern/include/ros/bits/syscall.h
kern/src/Makefrag
kern/src/kfs.c
kern/src/manager.c
kern/src/process.c
kern/src/syscall.c
tests/fillmeup.c [new file with mode: 0644]
tools/packetizer/Makefile [new file with mode: 0644]
tools/packetizer/packetizer.cpp [new file with mode: 0644]
tools/packetizer/packetizer.h [new file with mode: 0644]
tools/packetizer/test_file [new file with mode: 0644]

index 4be26c5..5d8dd8f 100644 (file)
@@ -391,7 +391,28 @@ void ne2k_handle_rx_packet() {
                return;
        }
 
+#ifdef __CONFIG_OSDI__
+       struct packetizer_packet *p = (struct packetizer_packet*)rx_buffer;
+       if(ntohs(p->ethertype) == PACKETIZER_ETH_TYPE) {
+               assert(fillmeup_data.proc != NULL);
+               assert(fillmeup_data.bufs != NULL);
+               struct proc *proc = fillmeup_data.proc;
+
+               int16_t lw;
+               memcpy_from_user(proc, &lw, fillmeup_data.last_written, sizeof(lw));
+               lw = (lw + 1) % (fillmeup_data.num_bufs);
+               memcpy_to_user(proc, fillmeup_data.last_written, &lw, sizeof(lw));
+               memcpy_to_user(proc, &fillmeup_data.bufs[PACKETIZER_MAX_PAYLOAD * lw], 
+                              p->payload, ntohl(p->payload_size));
+               //print_packetizer_packet(p);
+               proc_notify(fillmeup_data.proc, NE_ETC_ETC_ETC, 0);
 
+               kfree(rx_buffer);
+               return;
+       }
+#endif
+
+#ifdef __CONFIG_APPSERVER__
        // Treat as a syscall frontend response packet if eth_type says so
        // Will eventually go away, so not too worried about elegance here...
        #include <frontend.h>
@@ -402,6 +423,7 @@ void ne2k_handle_rx_packet() {
                kfree(rx_buffer);
                return;
        }
+#endif
 
        spin_lock(&packet_buffers_lock);
 
index 7156e62..9c130f2 100644 (file)
 #include <kmalloc.h>
 #include <stdio.h>
 
+#ifdef __CONFIG_OSDI__
+struct fillmeup fillmeup_data;
+#endif
+
 // Global send_frame function pointer
 // Means we can only have one network card per system right now...
 int (*send_frame)(const char *data, size_t len);
index 1c105b8..4ee4a21 100644 (file)
@@ -5,6 +5,57 @@
 #include <trap.h>
 #include <pmap.h>
 
+// Host to network format conversions and vice-versa
+static inline uint16_t htons(uint16_t x)
+{
+       __asm__ ("xchgb %%al,%%ah" : "=a" (x) : "a" (x));
+       return x;
+}
+
+static inline uint32_t htonl(uint32_t x)
+{
+       __asm__ ("bswapl %0" : "=r" (x) : "0" (x));
+       return x;
+}
+#define ntohs htons
+#define ntohl htonl
+
+#ifdef __CONFIG_OSDI__
+#define PACKETIZER_ETH_TYPE 0xabcd
+#define PACKETIZER_MAX_PAYLOAD 1024
+struct packetizer_packet
+{
+    uint8_t dst_mac[6];
+    uint8_t src_mac[6];
+    uint16_t ethertype;
+    uint16_t seqno;
+    uint32_t payload_size;
+    char payload[PACKETIZER_MAX_PAYLOAD];
+};
+
+static void print_packetizer_packet(struct packetizer_packet *p)
+{
+       printk("packetizer_packet:\n");
+       printk("  dst_mac: %02x:%02x:%02x:%02x:%02x:%02x\n", 
+               p->dst_mac[0],p->dst_mac[1],p->dst_mac[2],
+               p->dst_mac[3],p->dst_mac[4],p->dst_mac[5]);
+       printk("  src_mac: %02x:%02x:%02x:%02x:%02x:%02x\n", 
+               p->src_mac[0],p->src_mac[1],p->src_mac[2],
+               p->src_mac[3],p->src_mac[4],p->src_mac[5]);
+       printk("  ethertype: 0x%02x\n", ntohs(p->ethertype));
+       printk("  seqno: %u\n", ntohs(p->seqno));
+       printk("  payload_size: %u\n", ntohl(p->payload_size));
+}
+
+struct fillmeup {
+       struct proc *proc;
+       uint8_t *bufs;
+       uint16_t num_bufs;
+       int16_t *last_written;
+};
+extern struct fillmeup fillmeup_data;
+#endif
+
 // Packet sizes
 #define MTU              1500
 #define MAX_FRAME_SIZE   (MTU + 14)
@@ -29,21 +80,6 @@ extern uint32_t packet_buffers_head;
 extern uint32_t packet_buffers_tail;
 extern spinlock_t packet_buffers_lock; 
 
-// Host to network format conversions and vice-versa
-static inline uint16_t htons(uint16_t x)
-{
-       __asm__ ("xchgb %%al,%%ah" : "=a" (x) : "a" (x));
-       return x;
-}
-
-static inline uint32_t htonl(uint32_t x)
-{
-       __asm__ ("bswapl %0" : "=r" (x) : "0" (x));
-       return x;
-}
-#define ntohs htons
-#define ntohl htonl
-
 // Creates a new ethernet packet and puts the header on it
 char* eth_wrap(const char* data, size_t len, char src_mac[6], 
                char dest_mac[6], uint16_t eth_type);
index a2a155c..5729b26 100644 (file)
@@ -3,7 +3,6 @@
 
 /* system call numbers.  need to #def them for use in assembly. */
 #define SYS_null                                        1
-#define SYS_cache_buster                        2
 #define SYS_cache_invalidate            3
 #define SYS_reboot                                      4
 #define SYS_cputs                                       5
 #define SYS_tcgetattr                  117
 #define SYS_tcsetattr                  118
 
+/* Syscalls we plan to remove someday */
+#define SYS_cache_buster        200 
+#define SYS_fillmeup            201
+
 /* For Buster Measurement Flags */
 #define BUSTER_SHARED                  0x0001
 #define BUSTER_STRIDED                 0x0002
index 9dd077d..123f1b9 100644 (file)
@@ -63,7 +63,8 @@ KERN_APPFILES += \
                  $(TESTS_DIR)/mhello \
                  $(TESTS_DIR)/manycore_test \
                  $(TESTS_DIR)/pthread_test \
-                 $(TESTS_DIR)/idle
+                 $(TESTS_DIR)/idle \
+                 $(TESTS_DIR)/fillmeup
 endif
 
 KERN_LDFLAGS   := $(KERN_LDFLAGS) -L$(OBJDIR)/$(KERN_DIR) \
index 9d56593..b11c3d5 100644 (file)
@@ -51,6 +51,7 @@ DECL_PROG(mhello);
 DECL_PROG(manycore_test);
 DECL_PROG(pthread_test);
 DECL_PROG(idle);
+DECL_PROG(fillmeup);
 DECL_FILE(kfs_test_txt);
 DECL_FILE(hello_txt);
 #endif
@@ -69,6 +70,7 @@ struct kfs_entry kfs[MAX_KFS_FILES] = {
        KFS_PENTRY(manycore_test)
        KFS_PENTRY(pthread_test)
        KFS_PENTRY(idle)
+       KFS_PENTRY(fillmeup)
        KFS_FENTRY(kfs_test_txt)
        KFS_FENTRY(hello_txt)
 #endif
index 200ad95..4a2a90a 100644 (file)
@@ -155,7 +155,7 @@ void manager_klueska()
 
        if (progress == 0) {
                progress++;
-               envs[0] = kfs_proc_create(kfs_lookup_path("parlib_matrix"));
+               envs[0] = kfs_proc_create(kfs_lookup_path("fillmeup"));
                __proc_set_state(envs[0], PROC_RUNNABLE_S);
                proc_run(envs[0]);
        }
index 6d0aa4a..787f4b5 100644 (file)
@@ -731,6 +731,7 @@ void proc_yield(struct proc *SAFE p, bool being_nice)
 void do_notify(struct proc *p, uint32_t vcoreid, unsigned int notif,
                struct notif_event *ne)
 {
+       printd("sending notif %d to proc %p\n", notif, p);
        assert(notif < MAX_NR_NOTIF);
        if (ne)
                assert(notif == ne->ne_type);
@@ -738,6 +739,7 @@ void do_notify(struct proc *p, uint32_t vcoreid, unsigned int notif,
        struct notif_method *nm = &p->procdata->notif_methods[notif];
        struct preempt_data *vcpd = &p->procdata->vcore_preempt_data[vcoreid];
 
+       printd("nm = %p, vcpd = %p\n", nm, vcpd);
        /* enqueue notif message or toggle bits */
        if (ne && nm->flags & NOTIF_MSG) {
                if (bcq_enqueue(&vcpd->notif_evts, ne, NR_PERCORE_EVENTS, 4)) {
@@ -763,7 +765,7 @@ void do_notify(struct proc *p, uint32_t vcoreid, unsigned int notif,
                         */
                        if ((p->state & PROC_RUNNING_M) && // TODO: (VC#) (_S state)
                                      (p->procinfo->vcoremap[vcoreid].valid)) {
-                               printk("[kernel] sending notif to vcore %d\n", vcoreid);
+                               printd("[kernel] sending notif to vcore %d\n", vcoreid);
                                send_kernel_message(p->procinfo->vcoremap[vcoreid].pcoreid,
                                                    __notify, p, 0, 0, KMSG_ROUTINE);
                        } else { // TODO: think about this, fallback, etc
index e5f6bfb..eb56233 100644 (file)
@@ -1023,6 +1023,21 @@ intreg_t sys_tcsetattr(struct proc* p, int fd, int optional_actions, const void*
        user_memdup_free(p,kbuf);
        return ret;
 }
+
+#ifdef __CONFIG_OSDI__
+intreg_t sys_fillmeup(struct proc *p, uint8_t *bufs, 
+                      uint16_t num_bufs, int16_t *last_written)
+{
+       extern struct fillmeup fillmeup_data;
+       fillmeup_data.proc = p;
+       fillmeup_data.bufs = bufs;
+       fillmeup_data.num_bufs = num_bufs;
+       fillmeup_data.last_written = last_written;
+       *last_written = -1;
+       return 0;
+}
+#endif
+
 /************** Syscall Invokation **************/
 
 /* Executes the given syscall.
@@ -1082,6 +1097,9 @@ intreg_t syscall(struct proc *p, uintreg_t syscallno, uintreg_t a1,
                [SYS_eth_get_mac_addr] = (syscall_t)sys_eth_get_mac_addr,
                [SYS_eth_recv_check] = (syscall_t)sys_eth_recv_check,
        #endif
+       #ifdef __CONFIG_OSDI__
+               [SYS_fillmeup] = (syscall_t)sys_fillmeup,
+       #endif
                // Syscalls serviced by the appserver for now.
                [SYS_read] = (syscall_t)sys_read,
                [SYS_write] = (syscall_t)sys_write,
diff --git a/tests/fillmeup.c b/tests/fillmeup.c
new file mode 100644 (file)
index 0000000..0cc91e3
--- /dev/null
@@ -0,0 +1,83 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <ros/syscall.h>
+#include <vcore.h>
+#include <assert.h>
+#include <parlib.h>
+
+#define BUF_SIZE 1024
+#define NUM_BUFS 1024
+uint8_t bufs[BUF_SIZE * NUM_BUFS];
+int16_t last_written;
+
+void *mytls_desc = NULL;
+
+void print_new_buf() 
+{
+       printf("I just woke up on my vcore!\n");
+       printf("Value of last_written: %d\n", last_written);
+//     printf("Contents of last written buffer:\n");
+//     for(int i=0; i<BUF_SIZE; i++)
+//             printf("0x%02x ", bufs[BUF_SIZE * last_written + i]);
+}
+
+void vcore_entry()
+{
+       uint32_t vcoreid = vcore_id();
+
+       struct preempt_data *vcpd = &__procdata.vcore_preempt_data[vcoreid];
+       struct vcore *vc = &__procinfo.vcoremap[vcoreid];
+
+       /* Should always have notifications disabled when coming in here. */
+       assert(vcpd->notif_enabled == FALSE);
+
+       /* Put this in the loop that deals with notifications.  It will return if
+        * there is no preempt pending. */ 
+       // TODO: prob make a handle_notif() function
+       if (vc->preempt_pending)
+               sys_yield(TRUE);
+       vcpd->notif_pending = 0;
+
+       if(last_written >= 0)
+               print_new_buf();
+               
+       /* Pop the user trap frame */
+       set_tls_desc(mytls_desc, vcoreid);
+       pop_ros_tf(&vcpd->notif_tf, vcoreid);
+       assert(0);
+}
+
+int main(int argc, char** argv)
+{
+/* begin: stuff userspace needs to do before switching to multi-mode */
+       if (vcore_init())
+               printf("vcore_init() failed, we're fucked!\n");
+
+       /* tell the kernel where and how we want to receive notifications */
+       struct notif_method *nm;
+       nm = &__procdata.notif_methods[NE_NONE];
+       nm->flags |= NOTIF_WANTED | NOTIF_IPI;
+       nm->vcoreid = 0;
+       nm = &__procdata.notif_methods[NE_ETC_ETC_ETC];
+       nm->flags |= NOTIF_WANTED | NOTIF_IPI;
+       nm->vcoreid = 0;
+
+       mytls_desc = get_tls_desc(0);
+
+       /* don't forget to enable notifs on vcore0 at some point */
+       struct preempt_data *vcpd;
+       vcpd = &__procdata.vcore_preempt_data[0];
+       vcpd->notif_enabled = TRUE;
+       
+/* end: stuff userspace needs to do before switching to multi-mode */
+
+       printf("About to fill me up!!\n");
+       ros_syscall(SYS_fillmeup, bufs, NUM_BUFS, &last_written, 0, 0);
+       vcore_request(1);
+       while(1) {
+               sys_halt_core(0);
+       }
+       return 0;
+}
+
+
diff --git a/tools/packetizer/Makefile b/tools/packetizer/Makefile
new file mode 100644 (file)
index 0000000..8f059fa
--- /dev/null
@@ -0,0 +1,2 @@
+all: packetizer.cpp
+       gcc -o packetizer -I. -lstdc++ packetizer.cpp
diff --git a/tools/packetizer/packetizer.cpp b/tools/packetizer/packetizer.cpp
new file mode 100644 (file)
index 0000000..fd64db5
--- /dev/null
@@ -0,0 +1,200 @@
+#include <net/if.h>
+#include <net/ethernet.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <packetizer.h>
+#include <stdexcept>
+#include <fstream>
+
+#ifdef DEBUG_MODE
+# define debug(...) (__VA_ARGS__)
+#else
+# define debug(...) do { } while(0)
+#endif
+
+packetizer::packetizer(const char *target_mac, const char *eth_device, 
+                            const char *filename)
+{
+       seqno = 0;
+       memcpy(this->target_mac, target_mac, 6);
+       strcpy(this->eth_device, eth_device);
+       strcpy(this->filename, filename);
+       memset(&myaddr, 0, sizeof(myaddr));
+
+       // setuid root to open a raw socket.  if we fail, too bad
+       seteuid(0);
+       sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+       seteuid(getuid());
+       if(sock < 0)
+         throw std::runtime_error("socket() failed! Maybe try running as root...");
+
+       myaddr.sll_ifindex = if_nametoindex(eth_device);
+       myaddr.sll_family = AF_PACKET;
+
+       int ret = bind(sock, (struct sockaddr *)&myaddr, sizeof(myaddr));
+       if (ret < 0)
+         throw std::runtime_error("bind() failed!");
+
+       struct timeval tv;
+       tv.tv_sec = 1;
+       tv.tv_usec = 0;
+       if(setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,&tv,sizeof(struct timeval)) < 0)
+         throw std::runtime_error("setsockopt() failed!");
+
+       // get MAC address of local ethernet device
+       struct ifreq ifr;
+       strcpy(ifr.ifr_name, eth_device);
+       ret = ioctl(sock, SIOCGIFHWADDR, (char *)&ifr);
+       if (ret < 0)
+         throw std::runtime_error("ioctl() failed!");
+       memcpy(&host_mac, &ifr.ifr_ifru.ifru_hwaddr.sa_data, 6);
+}
+
+int packetizer::start()
+{
+       std::ifstream file(filename, std::ios::in | std::ios::binary);
+       packet p(target_mac, host_mac, seqno, MAX_PAYLOAD_SIZE, NULL);
+
+       int ret;
+       printf("Starting to packetize the file: %s\n", filename);
+       file.read(p.payload, MAX_PAYLOAD_SIZE);
+       while(file) {
+               printf("Sending chunk %d\n", seqno);
+               ret = ::sendto(sock, (char*)&p, p.size(), 0,
+                              (sockaddr*)&myaddr,sizeof(myaddr));
+               if (ret < 0)
+                 throw std::runtime_error("sending packet failed!");
+               p.header.seqno = htons(next_seqno());
+               file.read(p.payload, MAX_PAYLOAD_SIZE);
+       }
+       if(file.gcount()) {
+               p.header.payload_size = ntohl(file.gcount());
+               p.packet_size = sizeof(p.header)+file.gcount();
+               
+               ret = ::sendto(sock, (char*)&p, p.size(), 0,
+                              (sockaddr*)&myaddr,sizeof(myaddr));
+               if (ret < 0)
+                 throw std::runtime_error("sending packet failed!");
+               printf("Sending chunk %d\n", seqno);
+       }
+       printf("Last chunk had %u bytes...\n", file.gcount());
+}
+
+int main(int argc, char** argv)
+{
+       char target_mac[] = {0x00, 0x24, 0x1d, 0x10, 0xa2, 0xb5};
+       char eth_device[] = "ros-tap1";
+       char filename[] = "test_file";
+       packetizer p(target_mac, eth_device, filename);
+       p.start();
+       return 0;
+}
+
+/*
+memif_t::error memif_x86_dma_t::read_chunk(uint32_t addr, uint32_t len, uint8_t* bytes, uint8_t asi, uint16_t pid)
+{
+       if(!htif->running)
+         return memif_t::Invalid;
+
+       x86_packet p(ros_mac,appsvr_mac,X86_CMD_LOAD,next_seqno(),0,addr,0);
+       p.header.payload_size = htonl(len);
+       for(int i=0; i<p.size(); i++) {
+         debug("%02x ", (unsigned char)*((char *)&p + i));
+       }
+       debug("\n\n");
+       send_packet(&p);
+       if(p.size() - sizeof(x86_packet_header) != len)
+         throw std::runtime_error("bad packet size");
+
+       memcpy(bytes,p.payload,len);
+
+       return memif_t::OK;
+}
+
+memif_t::error memif_x86_dma_t::write_chunk(uint32_t addr, uint32_t len, const uint8_t* bytes, uint8_t asi, uint16_t pid)
+{
+       if(!htif->running)
+         return memif_t::Invalid;
+
+       x86_packet p(ros_mac,appsvr_mac,X86_CMD_STORE,next_seqno(),len,addr,bytes);
+       send_packet(&p);
+       if(p.size() != sizeof(x86_packet_header))
+         throw std::runtime_error("bad packet size");
+
+       return memif_t::OK;
+}
+
+void memif_x86_dma_t::send_packet(x86_packet* packet)
+{
+       x86_packet response;
+
+       while(1)
+       //for(int i = 0; i < 10; i++)
+       {
+         int ret = ::sendto(sock,(char*)packet,packet->size(),0,
+                            (sockaddr*)&myaddr,sizeof(myaddr));
+         if(ret != packet->size())
+           continue;
+         
+         debug("wait for response \n");
+         while(1)
+         {
+           ret = ::read(sock,(char*)&response,X86_MAX_PACKET_SIZE);
+           if(ret == -1)
+           {
+             debug("timeout\n");
+             break;
+           }
+           if(response.header.ethertype != htons(RAMP_ETHERTYPE) || 
+              memcmp(response.header.src_mac,packet->header.dst_mac,6) != 0)
+             continue;
+           else
+             break;
+         }
+         if(ret == -1)
+           continue;
+         
+       if(ret == 60)
+               ret = sizeof(response.header) + ntohl(response.header.payload_size);
+
+         if(ntohl(response.header.payload_size) != ret-sizeof(response.header))
+         {
+         debug("ntohl(response.header.payload_size) != ret-sizeof(response.header)\n");
+           for(int i = 0; i < ret; i++)
+             debug("%02x ",(unsigned int)(unsigned char)((char*)&response)[i]);
+           debug("\n");
+           debug("packet size wrong\n");
+           continue;
+         }
+         response.packet_size = ret;
+
+         debug("got %d bytes: \n",ret);
+         for(int i = 0; i < ret; i++)
+           debug("%02x ",(unsigned int)(unsigned char)((char*)&response)[i]);
+         debug("\n");
+
+         // if we didn't send a broadcast packet, verify sender's mac
+         if(response.header.cmd != X86_CMD_ACK) {
+         debug("response.header.cmd != X86_CMD_ACK\n");
+           for(int i = 0; i < ret; i++)
+             debug("%02x ",(unsigned int)(unsigned char)((char*)&response)[i]);
+           debug("\n");
+           debug("packet type wrong\n");
+           continue;
+        }
+         if(response.header.seqno != packet->header.seqno) 
+           continue;
+         debug("got something good\n");
+
+         *packet = response;
+         return;
+       }
+
+       throw std::runtime_error("memif_sparc_dma_t::send_packet(): timeout");
+}
+*/
+
diff --git a/tools/packetizer/packetizer.h b/tools/packetizer/packetizer.h
new file mode 100644 (file)
index 0000000..78f933f
--- /dev/null
@@ -0,0 +1,70 @@
+#ifndef _PACKETIZER_H
+#define _PACKETIZER_H
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <netpacket/packet.h>
+
+#define PACKETIZER_ETHERTYPE 0xabcd
+#define MAX_PAYLOAD_SIZE 1024
+#define MAX_PACKET_SIZE (MAX_PAYLOAD_SIZE+sizeof(packet_header))
+struct packet_header
+{
+       uint8_t dst_mac[6];
+       uint8_t src_mac[6];
+       uint16_t ethertype;
+       uint16_t seqno;
+       uint32_t payload_size;
+};
+
+struct packet
+{
+       packet_header header;
+       char payload[MAX_PAYLOAD_SIZE];
+       uint32_t packet_size;
+
+       uint32_t size()
+       {
+         return packet_size;
+       }
+
+       packet() {}
+       packet(const char* dst_mac, const char* src_mac, 
+              char seqno,int payload_size, const uint8_t* bytes)
+       {
+         header.ethertype = htons(PACKETIZER_ETHERTYPE);
+         memcpy(header.dst_mac,dst_mac,6);
+         memcpy(header.src_mac,src_mac,6);
+         header.seqno = htons(seqno);
+         header.payload_size = ntohl(payload_size);
+         if(bytes)
+           memcpy(payload,bytes,payload_size);
+         packet_size = sizeof(header)+payload_size;
+       }
+};
+
+class packetizer
+{
+public:
+       
+       packetizer(const char *target_mac, const char *eth_device, 
+                  const char *filename);
+       int start(void); 
+
+protected:
+
+       sockaddr_ll myaddr;
+       int sock;
+       char host_mac[6];
+       char target_mac[6];
+       char eth_device[64];
+       char filename[256];
+
+       void send_packet(packet* packet);
+
+       uint16_t seqno;
+       uint16_t next_seqno() { return seqno++; }
+};
+
+#endif // _PACKETIZER_H
diff --git a/tools/packetizer/test_file b/tools/packetizer/test_file
new file mode 100644 (file)
index 0000000..a71884c
--- /dev/null
@@ -0,0 +1,518 @@
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...
+I am here...